Browse Source

Merge branch 'develop' into enhancement/rollup

pull/6853/head
աɨռɢӄաօռɢ 1 year ago
parent
commit
9f7a1e0926
  1. 2
      .github/uffizzi/docker-compose.uffizzi.yml
  2. 2
      .github/workflows/release-docker.yml
  3. 2
      .github/workflows/release-npm.yml
  4. 2
      README.md
  5. 2
      docker-compose/mysql/docker-compose.yml
  6. 2
      docker-compose/nginx-proxy-manager/docker-compose.yml
  7. 4
      markdown/readme/languages/spanish.md
  8. 2
      package.json
  9. 4
      packages/nc-gui/assets/nc-icons/credit-card.svg
  10. 6
      packages/nc-gui/assets/nc-icons/layers.svg
  11. 4
      packages/nc-gui/assets/style.scss
  12. 9
      packages/nc-gui/components.d.ts
  13. 6
      packages/nc-gui/components/cell/DatePicker.vue
  14. 6
      packages/nc-gui/components/cell/DateTimePicker.vue
  15. 8
      packages/nc-gui/components/cell/Json.vue
  16. 29
      packages/nc-gui/components/cell/MultiSelect.vue
  17. 347
      packages/nc-gui/components/cell/RichText.vue
  18. 244
      packages/nc-gui/components/cell/RichText/LinkOptions.vue
  19. 381
      packages/nc-gui/components/cell/RichText/SelectedBubbleMenu.vue
  20. 68
      packages/nc-gui/components/cell/RichText/SelectedBubbleMenuPopup.vue
  21. 16
      packages/nc-gui/components/cell/SingleSelect.vue
  22. 181
      packages/nc-gui/components/cell/TextArea.vue
  23. 8
      packages/nc-gui/components/cell/attachment/Modal.vue
  24. 10
      packages/nc-gui/components/cell/attachment/index.vue
  25. 38
      packages/nc-gui/components/dashboard/Sidebar/UserInfo.vue
  26. 35
      packages/nc-gui/components/dashboard/TreeView/BaseOptions.vue
  27. 111
      packages/nc-gui/components/dashboard/TreeView/ProjectNode.vue
  28. 116
      packages/nc-gui/components/dashboard/TreeView/TableNode.vue
  29. 8
      packages/nc-gui/components/dashboard/TreeView/ViewsNode.vue
  30. 7
      packages/nc-gui/components/dlg/AirtableImport.vue
  31. 136
      packages/nc-gui/components/dlg/ColumnDuplicate.vue
  32. 16
      packages/nc-gui/components/dlg/QuickImport.vue
  33. 8
      packages/nc-gui/components/dlg/share-and-collaborate/SharePage.vue
  34. 2
      packages/nc-gui/components/general/EmojiPicker.vue
  35. 49
      packages/nc-gui/components/general/OpenLeftSidebarBtn.vue
  36. 3
      packages/nc-gui/components/nc/Button.vue
  37. 5
      packages/nc-gui/components/nc/Switch.vue
  38. 10
      packages/nc-gui/components/smartsheet/Cell.vue
  39. 33
      packages/nc-gui/components/smartsheet/Form.vue
  40. 8
      packages/nc-gui/components/smartsheet/Pagination.vue
  41. 2
      packages/nc-gui/components/smartsheet/Toolbar.vue
  42. 7
      packages/nc-gui/components/smartsheet/VirtualCell.vue
  43. 6
      packages/nc-gui/components/smartsheet/column/DecimalOptions.vue
  44. 123
      packages/nc-gui/components/smartsheet/column/EditOrAdd.vue
  45. 4
      packages/nc-gui/components/smartsheet/column/FormulaOptions.vue
  46. 38
      packages/nc-gui/components/smartsheet/column/LongTextOptions.vue
  47. 26
      packages/nc-gui/components/smartsheet/column/RichLongTextDefaultValue.vue
  48. 48
      packages/nc-gui/components/smartsheet/column/SelectOptions.vue
  49. 102
      packages/nc-gui/components/smartsheet/details/Fields.vue
  50. 4
      packages/nc-gui/components/smartsheet/expanded-form/Comments.vue
  51. 38
      packages/nc-gui/components/smartsheet/expanded-form/index.vue
  52. 39
      packages/nc-gui/components/smartsheet/grid/GroupBy.vue
  53. 28
      packages/nc-gui/components/smartsheet/grid/GroupByLabel.vue
  54. 239
      packages/nc-gui/components/smartsheet/grid/Table.vue
  55. 8
      packages/nc-gui/components/smartsheet/grid/usePaginationShortcuts.ts
  56. 6
      packages/nc-gui/components/smartsheet/header/Cell.vue
  57. 8
      packages/nc-gui/components/smartsheet/header/CellIcon.ts
  58. 106
      packages/nc-gui/components/smartsheet/header/Menu.vue
  59. 6
      packages/nc-gui/components/smartsheet/header/VirtualCell.vue
  60. 4
      packages/nc-gui/components/smartsheet/header/VirtualCellIcon.ts
  61. 50
      packages/nc-gui/components/smartsheet/toolbar/GroupByMenu.vue
  62. 2
      packages/nc-gui/components/smartsheet/toolbar/OpenedViewAction.vue
  63. 98
      packages/nc-gui/components/smartsheet/toolbar/ViewActionMenu.vue
  64. 14
      packages/nc-gui/components/tabs/Smartsheet.vue
  65. 94
      packages/nc-gui/components/template/Editor.vue
  66. 5
      packages/nc-gui/components/virtual-cell/BelongsTo.vue
  67. 5
      packages/nc-gui/components/virtual-cell/HasMany.vue
  68. 13
      packages/nc-gui/components/virtual-cell/Links.vue
  69. 14
      packages/nc-gui/components/virtual-cell/Lookup.vue
  70. 5
      packages/nc-gui/components/virtual-cell/ManyToMany.vue
  71. 3
      packages/nc-gui/components/virtual-cell/QrCode.vue
  72. 8
      packages/nc-gui/components/virtual-cell/components/Header.vue
  73. 11
      packages/nc-gui/components/virtual-cell/components/ItemChip.vue
  74. 9
      packages/nc-gui/components/virtual-cell/components/ListChildItems.vue
  75. 5
      packages/nc-gui/components/virtual-cell/components/ListItem.vue
  76. 69
      packages/nc-gui/components/virtual-cell/components/ListItems.vue
  77. 10
      packages/nc-gui/composables/useColumnCreateStore.ts
  78. 4
      packages/nc-gui/composables/useData.ts
  79. 1
      packages/nc-gui/composables/useGlobal/state.ts
  80. 1
      packages/nc-gui/composables/useGlobal/types.ts
  81. 4
      packages/nc-gui/composables/useMultiSelect/index.ts
  82. 58
      packages/nc-gui/composables/useTableNew.ts
  83. 6
      packages/nc-gui/composables/useViewData.ts
  84. 10
      packages/nc-gui/composables/useViewGroupBy.ts
  85. 131
      packages/nc-gui/helpers/dbTiptapExtensions/links.ts
  86. 186
      packages/nc-gui/helpers/dbTiptapExtensions/task-item.ts
  87. 580
      packages/nc-gui/lang/ar.json
  88. 580
      packages/nc-gui/lang/bn_IN.json
  89. 628
      packages/nc-gui/lang/cs.json
  90. 604
      packages/nc-gui/lang/da.json
  91. 666
      packages/nc-gui/lang/de.json
  92. 33
      packages/nc-gui/lang/en.json
  93. 640
      packages/nc-gui/lang/es.json
  94. 584
      packages/nc-gui/lang/eu.json
  95. 718
      packages/nc-gui/lang/fa.json
  96. 580
      packages/nc-gui/lang/fi.json
  97. 620
      packages/nc-gui/lang/fr.json
  98. 698
      packages/nc-gui/lang/he.json
  99. 582
      packages/nc-gui/lang/hi.json
  100. 1016
      packages/nc-gui/lang/hr.json
  101. Some files were not shown because too many files have changed in this diff Show More

2
.github/uffizzi/docker-compose.uffizzi.yml

@ -31,7 +31,7 @@ services:
MYSQL_PASSWORD: password
MYSQL_ROOT_PASSWORD: password
MYSQL_USER: noco
image: "mysql:8.0.32"
image: "mysql:8.0.35"
deploy:
resources:
limits:

2
.github/workflows/release-docker.yml

@ -92,7 +92,7 @@ jobs:
export NODE_OPTIONS="--max_old_space_size=16384"
NOCODB_SDK_PKG_NAME=nocodb-sdk-daily
targetEnv=${{ github.event.inputs.targetEnv || inputs.targetEnv }} targetVersion=${{ github.event.inputs.tag || inputs.tag }} node scripts/bumpNocodbSdkVersion.js &&
pnpm --filter=${NOCODB_SDK_PKG_NAME} install --ignore-scripts --no-frozen-lockfile && pnpm --filter=${NOCODB_SDK_PKG_NAME} run build &&
pnpm --filter=${NOCODB_SDK_PKG_NAME} install --ignore-scripts --no-frozen-lockfile --ignore-workspace && pnpm --filter=${NOCODB_SDK_PKG_NAME} run build &&
targetEnv=${{ github.event.inputs.targetEnv || inputs.targetEnv }} node scripts/upgradeNocodbSdk.js &&
targetEnv=${{ github.event.inputs.targetEnv || inputs.targetEnv }} targetVersion=${{ github.event.inputs.tag || inputs.tag }} node scripts/bumpNcGuiVersion.js &&
pnpm --filter=nc-gui install --ignore-scripts --no-frozen-lockfile &&

2
.github/workflows/release-npm.yml

@ -61,7 +61,7 @@ jobs:
fi
echo $NOCODB_SDK_PKG_NAME
targetEnv=${{ github.event.inputs.targetEnv || inputs.targetEnv }} targetVersion=${{ github.event.inputs.tag || inputs.tag }} node scripts/bumpNocodbSdkVersion.js &&
pnpm --filter=${NOCODB_SDK_PKG_NAME} install --ignore-scripts --no-frozen-lockfile && pnpm --filter=${NOCODB_SDK_PKG_NAME} run build && pnpm --filter=${NOCODB_SDK_PKG_NAME} publish --no-git-checks &&
pnpm --filter=${NOCODB_SDK_PKG_NAME} install --ignore-scripts --no-frozen-lockfile --ignore-workspace && pnpm --filter=${NOCODB_SDK_PKG_NAME} run build && pnpm --filter=${NOCODB_SDK_PKG_NAME} publish --no-git-checks &&
sleep 90 &&
targetEnv=${{ github.event.inputs.targetEnv || inputs.targetEnv }} node scripts/upgradeNocodbSdk.js &&
targetEnv=${{ github.event.inputs.targetEnv || inputs.targetEnv }} targetVersion=${{ github.event.inputs.tag || inputs.tag }} node scripts/bumpNcGuiVersion.js &&

2
README.md

@ -64,7 +64,7 @@ Turns any MySQL, PostgreSQL, SQL Server, SQLite & MariaDB into a smart spreadshe
</a>
-->
[![Stargazers repo roster for @nocodb/nocodb](https://reporoster.com/stars/nocodb/nocodb)](https://github.com/nocodb/nocodb/stargazers)
[![Stargazers repo roster for @nocodb/nocodb](http://reporoster.com/stars/nocodb/nocodb)](https://github.com/nocodb/nocodb/stargazers)
# Quick try

2
docker-compose/mysql/docker-compose.yml

@ -27,7 +27,7 @@ services:
- "-h"
- localhost
timeout: 20s
image: "mysql:8.0.32"
image: "mysql:8.0.35"
restart: always
volumes:
- "db_data:/var/lib/mysql"

2
docker-compose/nginx-proxy-manager/docker-compose.yml

@ -46,7 +46,7 @@ services:
- "-h"
- localhost
timeout: 20s
image: "mysql:8.0.32"
image: "mysql:8.0.35"
networks:
- default
restart: always

4
markdown/readme/languages/spanish.md

@ -194,8 +194,8 @@ Por favor diríjase a [Contribution Guide](https://github.com/nocodb/nocodb/blob
# Por qué estamos construyendo esto?
La mayoría de las empresas de Internet emplean una hoja de cálculo o una base de datos para resolver sus necesidades comerciales. Las hojas de cálculo son utilizadas por billones de personas o más de manera colaborativa todos los días. Sin embargo, estamos lejos de trabajar a velocidades similares en bases de datos, ya que son herramientas computacionalmente más poderosas. Los intentos de resolver esto con soluciones SaaS han significado horribles controles de acceso, dependencia de un proveedor, dependencia de datos, cambios abruptos de precios y lo que es más importante, un techo de cristal sobre lo que es posible en el futuro."
La mayoría de las empresas de Internet emplean una hoja de cálculo o una base de datos para resolver sus necesidades comerciales. Las hojas de cálculo son utilizadas por billones de personas o más de manera colaborativa todos los días. Sin embargo, estamos lejos de trabajar a velocidades similares en bases de datos, ya que son herramientas computacionalmente más poderosas. Los intentos de resolver esto con soluciones SaaS han significado horribles controles de acceso, dependencia de un proveedor, dependencia de datos, cambios abruptos de precios y lo que es más importante, un techo de cristal sobre lo que es posible en el futuro.
# Nuestra misión
Nuestra misión es proporcionar la interfaz sin-código más potente para bases de datos, la cual es open-source para negocios de Internet en el mundo. Esto no solo democratizaría el acceso a una poderosa herramienta de computación, sino que también producirá a billones de personas o más con habilidades radicales de perfección y construcción en Internet."
Nuestra misión es proporcionar la interfaz sin-código más potente para bases de datos, la cual es open-source para negocios de Internet en el mundo. Esto no solo democratizaría el acceso a una poderosa herramienta de computación, sino que también producirá a miles de millones de personas o más con habilidades radicales de perfección y construcción en Internet.

2
package.json

@ -18,7 +18,7 @@
"devDependencies": {
"fs": "0.0.1-security",
"lerna": "^7.0.2",
"husky": "^8.0.0",
"husky": "^8.0.3",
"xlsx": "^0.17.4"
},
"husky": {

4
packages/nc-gui/assets/nc-icons/credit-card.svg

@ -1,4 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14 2.66602H1.99999C1.26361 2.66602 0.666656 3.26297 0.666656 3.99935V11.9993C0.666656 12.7357 1.26361 13.3327 1.99999 13.3327H14C14.7364 13.3327 15.3333 12.7357 15.3333 11.9993V3.99935C15.3333 3.26297 14.7364 2.66602 14 2.66602Z" stroke="#565B66" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M0.666656 6.66602H15.3333" stroke="#565B66" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M14 2.66602H1.99999C1.26361 2.66602 0.666656 3.26297 0.666656 3.99935V11.9993C0.666656 12.7357 1.26361 13.3327 1.99999 13.3327H14C14.7364 13.3327 15.3333 12.7357 15.3333 11.9993V3.99935C15.3333 3.26297 14.7364 2.66602 14 2.66602Z" stroke="currentColor" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M0.666656 6.66602H15.3333" stroke="currentColor" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 557 B

After

Width:  |  Height:  |  Size: 567 B

6
packages/nc-gui/assets/nc-icons/layers.svg

@ -1,8 +1,8 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_656_42199)">
<path d="M1.33325 11.334L7.99992 14.6673L14.6666 11.334" stroke="#565B66" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M1.33325 8L7.99992 11.3333L14.6666 8" stroke="#565B66" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M7.99992 1.33398L1.33325 4.66732L7.99992 8.00065L14.6666 4.66732L7.99992 1.33398Z" stroke="#565B66" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M1.33325 11.334L7.99992 14.6673L14.6666 11.334" stroke="currentColor" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M1.33325 8L7.99992 11.3333L14.6666 8" stroke="currentColor" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M7.99992 1.33398L1.33325 4.66732L7.99992 8.00065L14.6666 4.66732L7.99992 1.33398Z" stroke="currentColor" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<defs>
<clipPath id="clip0_656_42199">

Before

Width:  |  Height:  |  Size: 712 B

After

Width:  |  Height:  |  Size: 727 B

4
packages/nc-gui/assets/style.scss

@ -678,3 +678,7 @@ input[type='number'] {
@apply xs:(visible opacity-100 !text-gray-500)
}
}
.ant-message-notice-content {
@apply !rounded-md;
}

9
packages/nc-gui/components.d.ts vendored

@ -26,7 +26,6 @@ declare module '@vue/runtime-core' {
AConfigProvider: typeof import('ant-design-vue/es')['ConfigProvider']
ADatePicker: typeof import('ant-design-vue/es')['DatePicker']
ADivider: typeof import('ant-design-vue/es')['Divider']
ADrawer: typeof import('ant-design-vue/es')['Drawer']
ADropdown: typeof import('ant-design-vue/es')['Dropdown']
ADropdownButton: typeof import('ant-design-vue/es')['DropdownButton']
AEmpty: typeof import('ant-design-vue/es')['Empty']
@ -47,7 +46,6 @@ declare module '@vue/runtime-core' {
AMenu: typeof import('ant-design-vue/es')['Menu']
AMenuDivider: typeof import('ant-design-vue/es')['MenuDivider']
AMenuItem: typeof import('ant-design-vue/es')['MenuItem']
AMenuItemGroup: typeof import('ant-design-vue/es')['MenuItemGroup']
AModal: typeof import('ant-design-vue/es')['Modal']
APagination: typeof import('ant-design-vue/es')['Pagination']
APopover: typeof import('ant-design-vue/es')['Popover']
@ -64,7 +62,6 @@ declare module '@vue/runtime-core' {
ASubMenu: typeof import('ant-design-vue/es')['SubMenu']
ASwitch: typeof import('ant-design-vue/es')['Switch']
ATable: typeof import('ant-design-vue/es')['Table']
ATableColumn: typeof import('ant-design-vue/es')['TableColumn']
ATabPane: typeof import('ant-design-vue/es')['TabPane']
ATabs: typeof import('ant-design-vue/es')['Tabs']
ATag: typeof import('ant-design-vue/es')['Tag']
@ -79,6 +76,7 @@ declare module '@vue/runtime-core' {
CilFullscreen: typeof import('~icons/cil/fullscreen')['default']
CilFullscreenExit: typeof import('~icons/cil/fullscreen-exit')['default']
ClaritySuccessLine: typeof import('~icons/clarity/success-line')['default']
IcBaselineArrowOutward: typeof import('~icons/ic/baseline-arrow-outward')['default']
IcBaselineMoreVert: typeof import('~icons/ic/baseline-more-vert')['default']
IcOutlineInsertDriveFile: typeof import('~icons/ic/outline-insert-drive-file')['default']
IcRoundEdit: typeof import('~icons/ic/round-edit')['default']
@ -126,6 +124,7 @@ declare module '@vue/runtime-core' {
MdiCodeTags: typeof import('~icons/mdi/code-tags')['default']
MdiContentCopy: typeof import('~icons/mdi/content-copy')['default']
MdiCurrencyUsd: typeof import('~icons/mdi/currency-usd')['default']
MdiDeleteOutline: typeof import('~icons/mdi/delete-outline')['default']
MdiDiscord: typeof import('~icons/mdi/discord')['default']
MdiDotsHorizontal: typeof import('~icons/mdi/dots-horizontal')['default']
MdiDotsVertical: typeof import('~icons/mdi/dots-vertical')['default']
@ -133,9 +132,13 @@ declare module '@vue/runtime-core' {
MdiFileDocumentMultipleOutline: typeof import('~icons/mdi/file-document-multiple-outline')['default']
MdiFileDocumentOutline: typeof import('~icons/mdi/file-document-outline')['default']
MdiFlag: typeof import('~icons/mdi/flag')['default']
MdiFormatBold: typeof import('~icons/mdi/format-bold')['default']
MdiFormatItalic: typeof import('~icons/mdi/format-italic')['default']
MdiFormatUnderline: typeof import('~icons/mdi/format-underline')['default']
MdiHeart: typeof import('~icons/mdi/heart')['default']
MdiHistory: typeof import('~icons/mdi/history')['default']
MdiKeyStar: typeof import('~icons/mdi/key-star')['default']
MdiLink: typeof import('~icons/mdi/link')['default']
MdiLinkVariant: typeof import('~icons/mdi/link-variant')['default']
MdiLoading: typeof import('~icons/mdi/loading')['default']
MdiLogin: typeof import('~icons/mdi/login')['default']

6
packages/nc-gui/components/cell/DatePicker.vue

@ -32,8 +32,6 @@ const columnMeta = inject(ColumnInj, null)!
const readOnly = inject(ReadonlyInj, ref(false))
const isLockedMode = inject(IsLockedInj, ref(false))
const isEditColumn = inject(EditColumnInj, ref(false))
const active = inject(ActiveCellInj, ref(false))
@ -188,9 +186,7 @@ useSelectedCellKeyupListener(active, (e: KeyboardEvent) => {
const isOpen = computed(() => {
if (readOnly.value) return false
return ((readOnly.value || (localState.value && isPk)) && !active.value && !editable.value) || isLockedMode.value
? false
: open.value
return (readOnly.value || (localState.value && isPk)) && !active.value && !editable.value ? false : open.value
})
// use the default date picker open sync only to close the picker

6
packages/nc-gui/components/cell/DateTimePicker.vue

@ -37,8 +37,6 @@ const active = inject(ActiveCellInj, ref(false))
const editable = inject(EditModeInj, ref(false))
const isLockedMode = inject(IsLockedInj, ref(false))
const { t } = useI18n()
const isEditColumn = inject(EditColumnInj, ref(false))
@ -126,9 +124,7 @@ const open = ref(false)
const isOpen = computed(() => {
if (readOnly.value) return false
return readOnly.value || (localState.value && isPk) || isLockedMode.value
? false
: open.value && (active.value || editable.value)
return readOnly.value || (localState.value && isPk) ? false : open.value && (active.value || editable.value)
})
const randomClass = `picker_${Math.floor(Math.random() * 99999)}`

8
packages/nc-gui/components/cell/Json.vue

@ -72,13 +72,7 @@ const clear = () => {
const formatJson = (json: string) => {
try {
json = json
.trim()
.replace(/^\{\s*|\s*\}$/g, '')
.replace(/\n\s*/g, '')
json = `{${json}}`
return json
return JSON.stringify(JSON.parse(json))
} catch (e) {
console.log(e)
return json

29
packages/nc-gui/components/cell/MultiSelect.vue

@ -49,8 +49,6 @@ const column = inject(ColumnInj)!
const readOnly = inject(ReadonlyInj)!
const isLockedMode = inject(IsLockedInj, ref(false))
const isEditable = inject(EditModeInj, ref(false))
const activeCell = inject(ActiveCellInj, ref(false))
@ -134,9 +132,13 @@ const vModel = computed({
const selectedTitles = computed(() =>
modelValue
? typeof modelValue === 'string'
? isMysql(column.value.source_id)
? modelValue.split(',').sort((a, b) => {
? Array.isArray(modelValue)
? modelValue
: isMysql(column.value.source_id)
? modelValue
.toString()
.split(',')
.sort((a, b) => {
const opa = options.value.find((el) => el.title === a)
const opb = options.value.find((el) => el.title === b)
if (opa && opb) {
@ -144,14 +146,13 @@ const selectedTitles = computed(() =>
}
return 0
})
: modelValue.split(',').map((el) => el.trim())
: modelValue.map((el) => el.trim())
: modelValue.toString().split(',')
: [],
)
onMounted(() => {
selectedIds.value = selectedTitles.value.flatMap((el) => {
const item = options.value.find((op) => op.title === el)
const item = options.value.find((op) => op.title === el || op.title === el?.trim())
const itemIdOrTitle = item?.id || item?.title
if (itemIdOrTitle) {
return [itemIdOrTitle]
@ -165,7 +166,7 @@ watch(
() => modelValue,
() => {
selectedIds.value = selectedTitles.value.flatMap((el) => {
const item = options.value.find((op) => op.title === el)
const item = options.value.find((op) => op.title === el || op.title === el?.trim())
if (item && (item.id || item.title)) {
return [(item.id || item.title)!]
}
@ -343,11 +344,7 @@ const selectedOpts = computed(() => {
</script>
<template>
<div
class="nc-multi-select h-full w-full flex items-center"
:class="{ 'read-only': readOnly || isLockedMode }"
@click="toggleMenu"
>
<div class="nc-multi-select h-full w-full flex items-center" :class="{ 'read-only': readOnly }" @click="toggleMenu">
<div
v-if="!active"
class="flex flex-wrap"
@ -386,9 +383,9 @@ const selectedOpts = computed(() => {
:bordered="false"
clear-icon
:show-search="!isMobileMode"
:show-arrow="editAllowed && !(readOnly || isLockedMode)"
:show-arrow="editAllowed && !readOnly"
:open="isOpen && editAllowed"
:disabled="readOnly || !editAllowed || isLockedMode"
:disabled="readOnly || !editAllowed"
:class="{ 'caret-transparent': !hasEditRoles }"
:dropdown-class-name="`nc-dropdown-multi-select-cell ${isOpen ? 'active' : ''}`"
@search="search"

347
packages/nc-gui/components/cell/RichText.vue

@ -0,0 +1,347 @@
<script lang="ts" setup>
import StarterKit from '@tiptap/starter-kit'
import TaskList from '@tiptap/extension-task-list'
import { EditorContent, useEditor } from '@tiptap/vue-3'
import TurndownService from 'turndown'
import { marked } from 'marked'
import { generateJSON } from '@tiptap/html'
import Underline from '@tiptap/extension-underline'
import { TaskItem } from '@/helpers/dbTiptapExtensions/task-item'
import { Link } from '@/helpers/dbTiptapExtensions/links'
const props = defineProps<{
value?: string | null
readonly?: boolean
syncValueChange?: boolean
showMenu?: boolean
fullMode?: boolean
}>()
const emits = defineEmits(['update:value'])
const turndownService = new TurndownService({})
turndownService.addRule('lineBreak', {
filter: (node) => {
return node.nodeName === 'BR'
},
replacement: () => {
return '<br />'
},
})
turndownService.addRule('taskList', {
filter: (node) => {
return node.nodeName === 'LI' && !!node.getAttribute('data-checked')
},
replacement: (content, node: any) => {
// Remove the first \n\n and last \n\n
const processContent = content.replace(/^\n\n/, '').replace(/\n\n$/, '')
const isChecked = node.getAttribute('data-checked') === 'true'
return `[${isChecked ? 'x' : ' '}] ${processContent}\n\n`
},
})
const checkListItem = {
name: 'checkListItem',
level: 'block',
tokenizer(src: string) {
src = src.split('\n\n')[0]
const isMatched = src.startsWith('[ ]') || src.startsWith('[x]') || src.startsWith('[X]')
if (isMatched) {
const isNotChecked = src.startsWith('[ ]')
let text = src.slice(3)
if (text[0] === ' ') text = text.slice(1)
const token = {
// Token to generate
type: 'checkListItem',
raw: src,
text,
tokens: [],
checked: !isNotChecked,
}
;(this as any).lexer.inline(token.text, token.tokens) // Queue this data to be processed for inline tokens
return token
}
return false
},
renderer(token: any) {
return `<ul data-type="taskList"><li data-checked="${
token.checked ? 'true' : 'false'
}" data-type="taskItem"><label><input type="checkbox" ${
token.checked ? 'checked="checked"' : ''
}><span></span></label><div>${(this as any).parser.parseInline(token.tokens)}</div></li></ul>` // parseInline to turn child tokens into HTML
},
}
marked.use({ extensions: [checkListItem] })
const editorDom = ref<HTMLElement | null>(null)
const vModel = useVModel(props, 'value', emits, { defaultValue: '' })
const tiptapExtensions = [
StarterKit,
TaskList,
TaskItem.configure({
nested: true,
}),
Underline,
Link,
]
const editor = useEditor({
extensions: tiptapExtensions,
onUpdate: ({ editor }) => {
const markdown = turndownService
.turndown(editor.getHTML().replaceAll(/<p><\/p>/g, '<br />'))
.replaceAll(/\n\n<br \/>\n\n/g, '<br>\n\n')
vModel.value = markdown
},
editable: !props.readonly,
})
const setEditorContent = (contentMd: any) => {
if (!editor.value) return
const selection = editor.value.view.state.selection
const contentHtml = contentMd ? marked.parse(contentMd) : '<p></p>'
const content = generateJSON(contentHtml, tiptapExtensions)
editor.value.chain().setContent(content).setTextSelection(selection.to).run()
setTimeout(() => {
;(editor.value!.state as any).history$.prevRanges = null
;(editor.value!.state as any).history$.done.eventCount = 0
}, 100)
}
if (props.syncValueChange) {
watch(vModel, () => {
setEditorContent(vModel.value)
})
}
watch(editorDom, () => {
if (!editorDom.value) return
setEditorContent(vModel.value)
// Focus editor after editor is mounted
setTimeout(() => {
editor.value?.chain().focus().run()
}, 50)
})
</script>
<template>
<div
class="h-full"
:class="{
'flex flex-col flex-grow nc-rich-text-full': props.fullMode,
'nc-rich-text-embed': !props.fullMode,
}"
>
<div v-if="props.showMenu" class="absolute top-0 right-0.5">
<CellRichTextSelectedBubbleMenu v-if="editor" :editor="editor" embed-mode />
</div>
<CellRichTextSelectedBubbleMenuPopup v-if="editor" :editor="editor" />
<CellRichTextLinkOptions v-if="editor" :editor="editor" />
<EditorContent
ref="editorDom"
:editor="editor"
class="flex flex-col nc-textarea-rich-editor w-full flex-grow"
:class="{
'ml-1 mt-2.5': props.fullMode,
}"
/>
</div>
</template>
<style lang="scss">
.nc-text-rich-scroll {
&::-webkit-scrollbar-thumb {
@apply bg-transparent;
}
}
.nc-text-rich-scroll:hover {
&::-webkit-scrollbar-thumb {
@apply bg-gray-200;
}
}
.nc-rich-text-embed {
.ProseMirror {
@apply !border-transparent;
}
}
.nc-rich-text-full {
@apply px-1.75;
.ProseMirror {
@apply !p-2;
max-height: calc(min(60vh, 100rem));
min-height: 8rem;
}
}
.nc-textarea-rich-editor {
.ProseMirror {
@apply flex-grow pt-1 border-1 border-gray-200 rounded-lg pr-1 mr-2;
> * {
@apply ml-1;
}
}
.ProseMirror-focused {
// remove all border
outline: none;
@apply border-brand-500;
}
p {
@apply !mb-1;
}
ul {
li {
@apply ml-4;
list-style-type: disc;
}
}
ol {
@apply -ml-6 !pl-4;
li {
list-style-type: decimal;
}
}
ul,
ol {
@apply !my-0;
}
ul[data-type='taskList'] {
@apply;
li {
@apply !ml-0 flex flex-row gap-x-2;
list-style-type: none;
input {
@apply mt-0.75 flex rounded-sm;
z-index: -10;
}
// Unchecked
input:not(:checked) {
// Add border to checkbox
border-width: 1.5px;
@apply border-gray-700;
}
}
}
// Pre tag is the parent wrapper for Code block
pre {
border-color: #d0d5dd;
border: 1px;
color: black;
font-family: 'JetBrainsMono', monospace;
padding: 1rem;
border-radius: 0.5rem;
@apply overflow-auto mt-3 bg-gray-100;
code {
@apply !px-0;
}
}
code {
@apply rounded-md px-2 py-1 bg-gray-100;
color: inherit;
font-size: 0.8rem;
}
h1 {
font-weight: 700;
font-size: 1.85rem;
margin-bottom: 0.1rem;
}
h2 {
font-weight: 600;
font-size: 1.55rem;
margin-bottom: 0.1em;
}
h3 {
font-weight: 600;
font-size: 1.15rem;
margin-bottom: 0.1em;
}
blockquote {
border-left: 3px solid #d0d5dd;
padding: 0 1em;
color: #666;
margin: 1em 0;
font-style: italic;
}
hr {
@apply !border-gray-300;
border: 0;
border-top: 1px solid #ccc;
margin: 1.5em 0;
}
pre {
height: fit-content;
}
}
.nc-rich-text-full {
.ProseMirror {
overflow-y: scroll;
overflow-x: hidden;
scrollbar-width: thin !important;
&::-webkit-scrollbar {
width: 4px;
height: 4px;
}
&::-webkit-scrollbar-track {
-webkit-border-radius: 10px;
border-radius: 10px;
margin-top: 4px;
margin-bottom: 4px;
}
&::-webkit-scrollbar-track-piece {
width: 0px;
}
&::-webkit-scrollbar {
@apply bg-transparent;
}
&::-webkit-scrollbar-thumb {
-webkit-border-radius: 10px;
border-radius: 10px;
width: 4px;
@apply bg-gray-300;
}
&::-webkit-scrollbar-thumb:hover {
@apply bg-gray-400;
}
}
}
</style>

244
packages/nc-gui/components/cell/RichText/LinkOptions.vue

@ -0,0 +1,244 @@
<script lang="ts" setup>
import type { Editor } from '@tiptap/vue-3'
import { BubbleMenu } from '@tiptap/vue-3'
import { getMarkRange } from '@tiptap/core'
import type { Mark } from 'prosemirror-model'
const props = defineProps<Props>()
interface Props {
editor: Editor
}
const editor = computed(() => props.editor)
const inputRef = ref<HTMLInputElement>()
const linkNodeMark = ref<Mark | undefined>()
const href = ref('')
const isLinkOptionsVisible = ref(false)
// This is used to prevent the menu from showing up after a link is deleted, an edge case when the link with empty placeholder text is deleted.
// This is because checkLinkMark is not called in that case
const justDeleted = ref(false)
// This function is called by BubbleMenu on selection change
// It is used to check if the link mark is active and only show the menu if it is
const checkLinkMark = (editor: Editor) => {
if (!editor.view.editable) return false
if (justDeleted.value) {
setTimeout(() => {
justDeleted.value = false
}, 100)
return false
}
const activeNode = editor?.state?.selection?.$from?.nodeBefore || editor?.state?.selection?.$from?.nodeAfter
const isLinkMarkedStoredInEditor = editor?.state?.storedMarks?.some((mark: Mark) => mark.type.name === 'link')
const isActiveNodeMarkActive = activeNode?.marks?.some((mark: Mark) => mark.type.name === 'link') || isLinkMarkedStoredInEditor
if (isActiveNodeMarkActive) {
linkNodeMark.value = activeNode?.marks.find((mark: Mark) => mark.type.name === 'link')
href.value = linkNodeMark.value?.attrs?.href
}
if (isLinkMarkedStoredInEditor) {
linkNodeMark.value = editor?.state?.storedMarks?.find((mark: Mark) => mark.type.name === 'link')
href.value = linkNodeMark.value?.attrs?.href
}
const isTextSelected = editor?.state?.selection?.from !== editor?.state?.selection?.to
// check if active node is a text node
const showLinkOptions = isActiveNodeMarkActive && !isTextSelected
isLinkOptionsVisible.value = !!showLinkOptions
return showLinkOptions
}
function notStartingWithNetworkProtocol(inputString: string) {
const pattern = /^(?![^:]+:\/\/).*/
const isMatch = pattern.test(inputString)
return isMatch
}
const onChange = () => {
const isLinkMarkedStoredInEditor = editor.value.state?.storedMarks?.some((mark: Mark) => mark.type.name === 'link')
let formatedHref = href.value
if (
isValidURL(href.value) &&
href.value.length > 0 &&
!href.value.startsWith('/') &&
notStartingWithNetworkProtocol(href.value)
) {
formatedHref = `https://${href.value}`
}
if (isLinkMarkedStoredInEditor) {
editor.value.view.dispatch(
editor.value.view.state.tr
.removeStoredMark(editor.value.schema.marks.link)
.addStoredMark(editor.value.schema.marks.link.create({ href: formatedHref })),
)
} else if (linkNodeMark.value) {
const selection = editor.value.state?.selection
const markSelection = getMarkRange(selection.$anchor, editor.value.schema.marks.link) as any
editor.value.view.dispatch(
editor.value.view.state.tr
.removeMark(markSelection.from, markSelection.to, editor.value.schema.marks.link)
.addMark(markSelection.from, markSelection.to, editor.value.schema.marks.link.create({ href: formatedHref })),
)
}
}
const onDelete = () => {
const isLinkMarkedStoredInEditor = editor.value.state?.storedMarks?.some((mark: Mark) => mark.type.name === 'link')
if (isLinkMarkedStoredInEditor) {
editor.value.view.dispatch(editor.value.view.state.tr.removeStoredMark(editor.value.schema.marks.link))
} else if (linkNodeMark.value) {
const selection = editor.value.state.selection
const markSelection = getMarkRange(selection.$anchor, editor.value.schema.marks.link) as any
editor.value.view.dispatch(
editor.value.view.state.tr.removeMark(markSelection.from, markSelection.to, editor.value.schema.marks.link),
)
}
justDeleted.value = true
}
const handleKeyDown = (e: any) => {
const isCtrlPressed = isMac() ? e.metaKey : e.ctrlKey
// Ctrl + Z/ Meta + Z
if (isCtrlPressed && e.key === 'z') {
e.preventDefault()
editor.value.commands.undo()
}
// Ctrl + Shift + Z/ Meta + Shift + Z
if (isCtrlPressed && e.shiftKey && e.key === 'z') {
e.preventDefault()
editor.value.commands.redo()
}
}
const onInputBoxEnter = () => {
inputRef.value?.blur()
editor.value.chain().focus().run()
}
const handleInputBoxKeyDown = (e: any) => {
if (e.key === 'ArrowDown' || e.key === 'Escape') {
editor.value.chain().focus().run()
}
}
watch(isLinkOptionsVisible, (value, oldValue) => {
if (value && !oldValue) {
const isPlaceholderEmpty =
!editor.value.state.selection.$from.nodeBefore?.textContent && !editor.value.state.selection.$from.nodeAfter?.textContent
if (!isPlaceholderEmpty) return
setTimeout(() => {
inputRef.value?.focus()
}, 100)
}
})
const openLink = () => {
if (href.value) {
window.open(href.value, '_blank', 'noopener,noreferrer')
}
}
</script>
<template>
<BubbleMenu :editor="editor" :tippy-options="{ duration: 100, maxWidth: 600 }" :should-show="(checkLinkMark as any)">
<div
v-if="!justDeleted"
ref="wrapperRef"
class="relative bubble-menu nc-text-area-rich-link-options flex flex-col bg-gray-50 py-1 px-1 rounded-lg"
data-testid="nc-text-area-rich-link-options"
@keydown.stop="handleKeyDown"
>
<div class="flex items-center gap-x-1">
<div class="!border-1 !border-gray-200 !py-0.5 bg-gray-100 rounded-md !z-10">
<a-input
ref="inputRef"
v-model:value="href"
class="nc-text-area-rich-link-option-input flex-1 !w-96 !mx-0.5 !px-1.5 !py-0.5 !rounded-md z-10"
:bordered="false"
placeholder="Enter a link"
@change="onChange"
@press-enter="onInputBoxEnter"
@keydown="handleInputBoxKeyDown"
/>
</div>
<NcTooltip overlay-class-name="nc-text-area-rich-link-options">
<template #title> Open link </template>
<NcButton
:class="{
'!text-gray-300 cursor-not-allowed': href.length === 0,
}"
data-testid="nc-text-area-rich-link-options-open-link"
size="small"
type="text"
@click="openLink"
>
<IcBaselineArrowOutward />
</NcButton>
</NcTooltip>
<NcTooltip overlay-class-name="nc-text-area-rich-link-options">
<template #title> Delete link </template>
<NcButton
class="!duration-0 !hover:(text-red-400 bg-red-50)"
data-testid="nc-text-area-rich-link-options-open-delete"
size="small"
type="text"
@click="onDelete"
>
<MdiDeleteOutline />
</NcButton>
</NcTooltip>
<div class="absolute -bottom-1.5 left-0 right-0 w-full flex flex-row justify-center">
<div
class="flex h-2.5 w-2.5 bg-white border-gray-200 border-r-1 border-b-1 transform rotate-45"
:style="{
boxShadow: '1px 1px 3px rgba(231, 231, 233, 1)',
}"
></div>
</div>
</div>
</div>
</BubbleMenu>
</template>
<style lang="scss">
.bubble-menu {
// shadow
@apply shadow-gray-200 shadow-sm;
}
.nc-text-area-rich-link-options {
.ant-popover-inner-content {
@apply !shadow-none !p-0;
}
.ant-popover-arrow {
@apply !shadow-none;
.ant-popover-arrow-content {
@apply !shadow-none !bg-gray-100;
}
}
.ant-popover-inner {
@apply !shadow-none !bg-gray-100 py-1.5 px-2.5 text-xs !rounded-sm;
}
}
</style>

381
packages/nc-gui/components/cell/RichText/SelectedBubbleMenu.vue

@ -0,0 +1,381 @@
<script lang="ts" setup>
import type { Editor } from '@tiptap/vue-3'
import MdiFormatBulletList from '~icons/mdi/format-list-bulleted'
import MdiFormatStrikeThrough from '~icons/mdi/format-strikethrough'
import MdiFormatListNumber from '~icons/mdi/format-list-numbered'
import MdiFormatListCheckbox from '~icons/mdi/format-list-checkbox'
import MsFormatH1 from '~icons/material-symbols/format-h1'
import MsFormatH2 from '~icons/material-symbols/format-h2'
import MsFormatH3 from '~icons/material-symbols/format-h3'
import TablerBlockQuote from '~icons/tabler/blockquote'
import MsCode from '~icons/material-symbols/code'
import MsFormatQuote from '~icons/material-symbols/format-quote'
interface Props {
editor: Editor
embedMode?: boolean
}
const props = defineProps<Props>()
const editor = computed(() => props.editor)
const embedMode = computed(() => props.embedMode)
const cmdOrCtrlKey = computed(() => {
return isMac() ? '⌘' : 'CTRL'
})
const shiftKey = computed(() => {
return isMac() ? '⇧' : 'Shift'
})
const altKey = computed(() => {
return isMac() ? '⌥' : 'Alt'
})
const onToggleLink = () => {
const activeNode = editor.value?.state?.selection?.$from?.nodeBefore || editor.value?.state?.selection?.$from?.nodeAfter
const isLinkMarkedStoredInEditor = editor.value?.state?.storedMarks?.some((mark: any) => mark.type.name === 'link')
const isActiveNodeMarkActive = activeNode?.marks?.some((mark: any) => mark.type.name === 'link') || isLinkMarkedStoredInEditor
if (isActiveNodeMarkActive) {
editor.value!.chain().focus().unsetLink().run()
} else {
if (editor.value.state.selection.empty) {
editor
.value!.chain()
.focus()
.insertContent(' ')
.setTextSelection({ from: editor.value!.state.selection.$from.pos, to: editor.value!.state.selection.$from.pos + 1 })
.toggleLink({
href: '',
})
.setTextSelection({ from: editor.value!.state.selection.$from.pos, to: editor.value!.state.selection.$from.pos + 1 })
.deleteSelection()
.run()
} else {
editor
.value!.chain()
.focus()
.setLink({
href: '',
})
.selectTextblockEnd()
.run()
}
setTimeout(() => {
const linkInput = document.querySelector('.nc-text-area-rich-link-option-input')
if (linkInput) {
;(linkInput as any).focus()
}
}, 100)
}
}
</script>
<template>
<div
class="bubble-menu flex flex-row gap-x-1 bg-gray-100 py-1 rounded-lg px-1"
:class="{
'embed-mode': embedMode,
'full-mode': !embedMode,
}"
>
<NcTooltip :disabled="editor.isActive('codeBlock')">
<template #title>
<div class="flex flex-col items-center">
<div>
{{ $t('labels.bold') }}
</div>
<div class="text-xs">{{ cmdOrCtrlKey }} B</div>
</div>
</template>
<NcButton
size="small"
type="text"
:class="{ 'is-active': editor.isActive('bold') }"
:disabled="editor.isActive('codeBlock')"
@click="editor!.chain().focus().toggleBold().run()"
>
<MdiFormatBold />
</NcButton>
</NcTooltip>
<NcTooltip :disabled="editor.isActive('codeBlock')">
<template #title>
<div class="flex flex-col items-center">
<div>
{{ $t('labels.italic') }}
</div>
<div>{{ cmdOrCtrlKey }} I</div>
</div>
</template>
<NcButton
size="small"
type="text"
:disabled="editor.isActive('codeBlock')"
:class="{ 'is-active': editor.isActive('italic') }"
@click=";(editor!.chain().focus() as any).toggleItalic().run()"
>
<MdiFormatItalic />
</NcButton>
</NcTooltip>
<NcTooltip :disabled="editor.isActive('codeBlock')">
<template #title>
<div class="flex flex-col items-center">
<div>
{{ $t('labels.underline') }}
</div>
<div>{{ cmdOrCtrlKey }} U</div>
</div>
</template>
<NcButton
size="small"
type="text"
:class="{ 'is-active': editor.isActive('underline') }"
:disabled="editor.isActive('codeBlock')"
@click="editor!.chain().focus().toggleUnderline().run()"
>
<MdiFormatUnderline />
</NcButton>
</NcTooltip>
<NcTooltip :disabled="editor.isActive('codeBlock')">
<template #title>
<div class="flex flex-col items-center">
<div>
{{ $t('labels.strike') }}
</div>
<div>{{ shiftKey }} {{ cmdOrCtrlKey }} S</div>
</div>
</template>
<NcButton
size="small"
type="text"
:class="{ 'is-active': editor.isActive('strike') }"
:disabled="editor.isActive('codeBlock')"
@click="editor!.chain().focus().toggleStrike().run()"
>
<MdiFormatStrikeThrough />
</NcButton>
</NcTooltip>
<NcTooltip v-if="embedMode">
<template #title> {{ $t('general.code') }}</template>
<NcButton
size="small"
type="text"
:class="{ 'is-active': editor.isActive('codeBlock') }"
@click="editor!.chain().focus().toggleCodeBlock().run()"
>
<MsCode />
</NcButton>
</NcTooltip>
<NcTooltip v-else :disabled="editor.isActive('codeBlock')">
<template #title> {{ $t('general.quote') }}</template>
<NcButton
size="small"
type="text"
:class="{ 'is-active': editor.isActive('code') }"
:disabled="editor.isActive('codeBlock')"
@click="editor!.chain().focus().toggleCode().run()"
>
<MsFormatQuote />
</NcButton>
</NcTooltip>
<div class="divider"></div>
<template v-if="embedMode">
<NcTooltip>
<template #title>
<div class="flex flex-col items-center">
<div>
{{ $t('labels.heading1') }}
</div>
<div>{{ cmdOrCtrlKey }} {{ altKey }} 1</div>
</div>
</template>
<NcButton
size="small"
type="text"
:class="{ 'is-active': editor.isActive('heading', { level: 1 }) }"
@click="editor!.chain().focus().toggleHeading({ level: 1 }).run()"
>
<MsFormatH1 />
</NcButton>
</NcTooltip>
<NcTooltip>
<template #title>
<div class="flex flex-col items-center">
<div>
{{ $t('labels.heading2') }}
</div>
<div>{{ cmdOrCtrlKey }} {{ altKey }} 2</div>
</div>
</template>
<NcButton
size="small"
type="text"
:class="{ 'is-active': editor.isActive('heading', { level: 2 }) }"
@click="editor!.chain().focus().toggleHeading({ level: 2 }).run()"
>
<MsFormatH2 />
</NcButton>
</NcTooltip>
<NcTooltip>
<template #title>
<div class="flex flex-col items-center">
<div>
{{ $t('labels.heading3') }}
</div>
<div>{{ cmdOrCtrlKey }} {{ altKey }} 3</div>
</div>
</template>
<NcButton
size="small"
type="text"
:class="{ 'is-active': editor.isActive('heading', { level: 3 }) }"
@click="editor!.chain().focus().toggleHeading({ level: 3 }).run()"
>
<MsFormatH3 />
</NcButton>
</NcTooltip>
<div class="divider"></div>
</template>
<NcTooltip v-if="embedMode">
<template #title> {{ $t('labels.blockQuote') }}</template>
<NcButton
size="small"
type="text"
:class="{ 'is-active': editor.isActive('blockquote') }"
@click="editor!.chain().focus().toggleBlockquote().run()"
>
<TablerBlockQuote class="-mt-0.25" />
</NcButton>
</NcTooltip>
<NcTooltip>
<template #title> {{ $t('labels.bulletList') }}</template>
<NcButton
size="small"
type="text"
:class="{ 'is-active': editor.isActive('bulletList') }"
@click="editor!.chain().focus().toggleBulletList().run()"
>
<MdiFormatBulletList />
</NcButton>
</NcTooltip>
<NcTooltip>
<template #title> {{ $t('labels.numberedList') }}</template>
<NcButton
size="small"
type="text"
:class="{ 'is-active': editor.isActive('orderedList') }"
@click="editor!.chain().focus().toggleOrderedList().run()"
>
<MdiFormatListNumber />
</NcButton>
</NcTooltip>
<NcTooltip>
<template #title> {{ $t('labels.taskList') }}</template>
<NcButton
size="small"
type="text"
:class="{ 'is-active': editor.isActive('taskList') }"
@click="editor!.chain().focus().toggleTaskList().run()"
>
<MdiFormatListCheckbox />
</NcButton>
</NcTooltip>
<div class="divider"></div>
<NcTooltip :disabled="editor.isActive('codeBlock')">
<template #title> {{ $t('general.link') }}</template>
<NcButton
size="small"
type="text"
:class="{ 'is-active': editor.isActive('link') }"
:disabled="editor.isActive('codeBlock')"
@click="onToggleLink"
>
<div class="flex flex-row items-center px-0.5">
<MdiLink />
<div class="!text-xs !ml-1">{{ $t('general.link') }}</div>
</div>
</NcButton>
</NcTooltip>
</div>
</template>
<style lang="scss">
.bubble-menu-hidden {
[data-tippy-root] {
opacity: 0;
height: 0;
overflow: hidden;
z-index: -1;
user-select: none;
}
}
.bubble-text-format-button-icon {
@apply px-1.5 py-0 border-1 border-gray-300 rounded-sm items-center justify-center;
font-size: 0.8rem;
font-weight: 600;
}
.bubble-text-format-button {
@apply rounded-md py-1 my-0 pl-2.5 pr-3 cursor-pointer items-center gap-x-2.5 hover:bg-gray-100;
}
.bubble-menu.full-mode {
@apply border-gray-100
box-shadow: 0px 0px 1.2rem 0 rgb(230, 230, 230) !important;
}
.bubble-menu.embed-mode {
@apply border-transparent !shadow-none;
}
.embed-mode.bubble-menu {
@apply !py-0 !my-0 !border-0;
.divider {
@apply my-0 !h-11 border-gray-100;
}
.nc-button {
@apply !mt-1.65;
}
}
.bubble-menu {
// shadow
@apply bg-white;
border-width: 1px;
.nc-button.is-active {
@apply !hover:outline-gray-200 bg-gray-100 text-brand-500;
outline: 1px;
}
.divider {
@apply border-r-1 border-gray-200 !h-6 !mx-0.5 my-1;
}
.ant-select-selector {
@apply !rounded-md;
}
.ant-select-selector .ant-select-selection-item {
@apply !text-xs;
}
.ant-btn-loading-icon {
@apply pb-0.5;
}
}
</style>

68
packages/nc-gui/components/cell/RichText/SelectedBubbleMenuPopup.vue

@ -0,0 +1,68 @@
<script lang="ts" setup>
import type { Editor } from '@tiptap/vue-3'
import { BubbleMenu } from '@tiptap/vue-3'
const props = defineProps<Props>()
interface Props {
editor: Editor
}
const editor = computed(() => props.editor)
// Debounce show menu to prevent flickering
const showMenu = computed(() => {
if (!editor) return false
return !editor.value.state.selection.empty
})
const showMenuDebounced = ref(false)
watchDebounced(
() => showMenu.value,
(value) => {
showMenuDebounced.value = value
},
{
debounce: 200,
maxWait: 800,
immediate: true,
},
)
const handleEditorMouseDown = (e: MouseEvent) => {
const domsInEvent = document.elementsFromPoint(e.clientX, e.clientY) as HTMLElement[]
const isBubble = domsInEvent.some((dom) => dom?.classList?.contains('bubble-menu'))
if (isBubble) return
const pageContent = document.querySelector('.nc-textarea-rich-editor')
pageContent?.classList.add('bubble-menu-hidden')
}
const handleEditorMouseUp = (e: MouseEvent) => {
const domsInEvent = document.elementsFromPoint(e.clientX, e.clientY) as HTMLElement[]
const isBubble = domsInEvent.some((dom) => dom?.classList?.contains('bubble-menu'))
if (isBubble) return
setTimeout(() => {
const pageContent = document.querySelector('.nc-textarea-rich-editor')
pageContent?.classList.remove('bubble-menu-hidden')
}, 100)
}
onMounted(() => {
document.addEventListener('mouseup', handleEditorMouseUp)
document.addEventListener('mousedown', handleEditorMouseDown)
})
onUnmounted(() => {
document.removeEventListener('mouseup', handleEditorMouseUp)
document.removeEventListener('mousedown', handleEditorMouseDown)
})
</script>
<template>
<BubbleMenu :editor="editor" :update-delay="300" :tippy-options="{ duration: 100, maxWidth: 600 }">
<CellRichTextSelectedBubbleMenu v-if="showMenuDebounced" :editor="editor" />
</BubbleMenu>
</template>

16
packages/nc-gui/components/cell/SingleSelect.vue

@ -43,8 +43,6 @@ const column = inject(ColumnInj)!
const readOnly = inject(ReadonlyInj)!
const isLockedMode = inject(IsLockedInj, ref(false))
const isEditable = inject(EditModeInj, ref(false))
const activeCell = inject(ActiveCellInj, ref(false))
@ -104,7 +102,7 @@ const hasEditRoles = computed(() => isUIAllowed('dataEdit'))
const editAllowed = computed(() => (hasEditRoles.value || isForm.value) && active.value)
const vModel = computed({
get: () => tempSelectedOptState.value ?? modelValue?.trim(),
get: () => tempSelectedOptState.value ?? modelValue,
set: (val) => {
if (val && isNewOptionCreateEnabled.value && (options.value ?? []).every((op) => op.title !== val)) {
tempSelectedOptState.value = val
@ -259,16 +257,12 @@ const handleClose = (e: MouseEvent) => {
useEventListener(document, 'click', handleClose, true)
const selectedOpt = computed(() => {
return options.value.find((o) => o.value === vModel.value)
return options.value.find((o) => o.value === vModel.value || o.value === vModel.value?.trim())
})
</script>
<template>
<div
class="h-full w-full flex items-center nc-single-select"
:class="{ 'read-only': readOnly || isLockedMode }"
@click="toggleMenu"
>
<div class="h-full w-full flex items-center nc-single-select" :class="{ 'read-only': readOnly }" @click="toggleMenu">
<div v-if="!(active || isEditable)">
<a-tag v-if="selectedOpt" class="rounded-tag" :color="selectedOpt.color">
<span
@ -295,8 +289,8 @@ const selectedOpt = computed(() => {
:allow-clear="!column.rqd && editAllowed"
:bordered="false"
:open="isOpen && editAllowed"
:disabled="readOnly || !editAllowed || isLockedMode"
:show-arrow="hasEditRoles && !(readOnly || isLockedMode) && active && vModel === null"
:disabled="readOnly || !editAllowed"
:show-arrow="hasEditRoles && !readOnly && active && vModel === null"
:dropdown-class-name="`nc-dropdown-single-select-cell ${isOpen && active ? 'active' : ''}`"
:show-search="!isMobileMode && isOpen && active"
@select="onSelect"

181
packages/nc-gui/components/cell/TextArea.vue

@ -16,6 +16,7 @@ import {
const props = defineProps<{
modelValue?: string | number
isFocus?: boolean
virtual?: boolean
}>()
const emits = defineEmits(['update:modelValue'])
@ -32,19 +33,33 @@ const isForm = inject(IsFormInj, ref(false))
const { showNull } = useGlobal()
const vModel = useVModel(props, 'modelValue', emits, { defaultValue: '' })
const vModel = useVModel(props, 'modelValue', emits, { defaultValue: column?.value.cdf ? String(column?.value.cdf) : '' })
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
const position = ref<
| {
top: number
left: number
}
| undefined
>({
top: 200,
left: 600,
})
const isDragging = ref(false)
const focus: VNodeRef = (el) => !isExpandedFormOpen.value && !isEditColumn.value && (el as HTMLTextAreaElement)?.focus()
const height = computed(() => {
if (!rowHeight.value) return 60
if (!rowHeight.value || rowHeight.value === 1) return 36
return rowHeight.value * 60
return rowHeight.value * 36
})
const isVisible = ref(false)
const inputWrapperRef = ref<HTMLElement | null>(null)
const inputRef = ref<HTMLTextAreaElement | null>(null)
@ -65,10 +80,96 @@ onClickOutside(inputWrapperRef, (e) => {
isVisible.value = false
})
const onTextClick = () => {
if (!props.virtual) return
isVisible.value = true
editEnabled.value = true
}
const isRichMode = computed(() => {
let meta: any = {}
if (typeof column?.value?.meta === 'string') {
meta = JSON.parse(column?.value?.meta)
} else {
meta = column?.value?.meta ?? {}
}
return meta?.richMode
})
const onExpand = () => {
isVisible.value = true
const { top, left } = inputWrapperRef.value?.getBoundingClientRect() ?? { top: 0, left: 0 }
position.value = {
top: top + 42,
left,
}
}
const onMouseMove = (e: MouseEvent) => {
if (!isDragging.value) return
e.stopPropagation()
position.value = {
top: e.clientY - 22,
left: e.clientX - 46,
}
}
const onMouseUp = (e: MouseEvent) => {
if (!isDragging.value) return
e.stopPropagation()
isDragging.value = false
position.value = undefined
document.removeEventListener('mousemove', onMouseMove)
document.removeEventListener('mouseup', onMouseUp)
}
watch(position, () => {
const dom = document.querySelector('.nc-textarea-dropdown-active') as HTMLElement
if (!dom) return
if (!position.value) return
// Set left and top of dom
setTimeout(() => {
if (!position.value) return
dom.style.left = `${position.value.left}px`
dom.style.top = `${position.value.top}px`
}, 100)
})
const dragStart = () => {
document.addEventListener('mousemove', onMouseMove)
document.addEventListener('mouseup', onMouseUp)
isDragging.value = true
}
watch(editEnabled, () => {
if (editEnabled.value) {
isVisible.value = true
}
})
</script>
<template>
<NcDropdown v-model:visible="isVisible" class="overflow-visible" :trigger="[]" placement="bottomLeft">
<NcDropdown
v-model:visible="isVisible"
class="overflow-visible"
:trigger="[]"
placement="bottomLeft"
:overlay-class-name="isVisible ? 'nc-textarea-dropdown-active' : undefined"
>
<div
class="flex flex-row pt-0.5 w-full"
:class="{
@ -77,8 +178,19 @@ onClickOutside(inputWrapperRef, (e) => {
'h-full': isForm,
}"
>
<div
v-if="isRichMode"
class="w-full cursor-pointer"
:style="{
maxHeight: `${height}px !important`,
minHeight: `${height}px !important`,
}"
@dblclick="onExpand"
>
<LazyCellRichText v-model:value="vModel" sync-value-change readonly class="!pointer-events-none" />
</div>
<textarea
v-if="editEnabled && !isVisible"
v-else-if="editEnabled && !isVisible"
:ref="focus"
v-model="vModel"
rows="4"
@ -113,42 +225,55 @@ onClickOutside(inputWrapperRef, (e) => {
class="mr-7 nc-text-area-clamped-text"
:style="{
'word-break': 'break-word',
'white-space': 'pre-line',
}"
@click="onTextClick"
/>
<span v-else>{{ vModel }}</span>
<div
v-if="active && !isExpandedFormOpen"
class="!absolute right-0 bottom-0 h-6 w-5 group cursor-pointer flex justify-end gap-1 items-center active:(ring ring-accent ring-opacity-100) rounded border-none p-1 hover:(bg-primary bg-opacity-10) dark:(!bg-slate-500)"
:class="{ 'right-2 bottom-2': editEnabled }"
data-testid="attachment-cell-file-picker-button"
@click.stop="isVisible = !isVisible"
<NcTooltip
v-if="!isVisible"
placement="bottom"
class="!absolute right-0 bottom-1 !hidden nc-text-area-expand-btn"
:class="{ 'right-0 bottom-1': editEnabled, '!bottom-0': !isRichMode }"
>
<NcTooltip placement="bottom">
<template #title>{{ $t('title.expand') }}</template>
<component
:is="iconMap.expand"
class="transform dark:(!text-white) group-hover:(!text-grey-800 scale-120) text-gray-500 text-xs"
/>
</NcTooltip>
</div>
<template #title>{{ $t('title.expand') }}</template>
<NcButton type="secondary" size="xsmall" data-testid="attachment-cell-file-picker-button" @click.stop="onExpand">
<component :is="iconMap.expand" class="transform group-hover:(!text-grey-800 ) scale-120 text-gray-700 text-xs" />
</NcButton>
</NcTooltip>
</div>
<template #overlay>
<div ref="inputWrapperRef" class="flex flex-col min-w-120 min-h-70 py-3 pl-3 pr-1 expanded-cell-input">
<div
v-if="isVisible"
ref="inputWrapperRef"
class="flex flex-col min-w-200 min-h-70 py-3 expanded-cell-input relative"
:class="{
'cursor-move': isDragging,
}"
>
<div
v-if="column"
class="flex flex-row gap-x-1 items-center font-medium pb-2.5 mb-1 py-1 mr-3 ml-1 border-b-1 border-gray-100"
class="flex flex-row gap-x-1 items-center font-medium pl-3 pb-2.5 border-b-1 border-gray-100 cursor-move"
:class="{
'select-none': isDragging,
}"
@mousedown="dragStart"
>
<SmartsheetHeaderCellIcon class="flex" />
<div class="flex">
{{ column.title }}
<div class="flex max-w-38">
<span class="truncate">
{{ column.title }}
</span>
</div>
</div>
<a-textarea
v-if="!isRichMode"
ref="inputRef"
v-model:value="vModel"
class="p-1 !pt-1 !pr-3 !border-0 !border-r-0 !focus:outline-transparent nc-scrollbar-md !text-black"
class="p-1 !pt-1 !pr-3 !border-0 !border-r-0 !focus:outline-transparent nc-scrollbar-md !text-black !cursor-text"
:placeholder="$t('activity.enterText')"
:bordered="false"
:auto-size="{ minRows: 20, maxRows: 20 }"
@ -156,13 +281,19 @@ onClickOutside(inputWrapperRef, (e) => {
@keydown.stop
@keydown.escape="isVisible = false"
/>
<LazyCellRichText v-else-if="isVisible" v-model:value="vModel" show-menu full-mode :read-only="readOnly" />
</div>
</template>
</NcDropdown>
</template>
<style>
<style lang="scss" scoped>
textarea:focus {
box-shadow: none;
}
:deep(.nc-text-area-expand-btn) {
@apply !block;
}
</style>

8
packages/nc-gui/components/cell/attachment/Modal.vue

@ -25,8 +25,6 @@ const {
renameFile,
} = useAttachmentCell()!
const isLocked = inject(IsLockedInj, ref(false))
const dropZoneRef = ref<HTMLDivElement>()
const sortableRef = ref<HTMLDivElement>()
@ -96,7 +94,7 @@ const handleFileDelete = (i: number) => {
<template #title>
<div class="flex gap-4">
<div
v-if="isSharedForm || (!readOnly && isUIAllowed('dataEdit') && !isPublic && !isLocked)"
v-if="isSharedForm || (!readOnly && isUIAllowed('dataEdit') && !isPublic)"
class="nc-attach-file group"
data-testid="attachment-expand-file-picker-button"
@click="open"
@ -143,7 +141,7 @@ const handleFileDelete = (i: number) => {
<template #title> {{ $t('title.removeFile') }} </template>
<component
:is="iconMap.closeCircle"
v-if="isSharedForm || (isUIAllowed('dataEdit') && !isPublic && !isLocked)"
v-if="isSharedForm || (isUIAllowed('dataEdit') && !isPublic)"
class="nc-attachment-remove"
@click.stop="onRemoveFileClick(item.title, i)"
/>
@ -157,7 +155,7 @@ const handleFileDelete = (i: number) => {
</div>
</a-tooltip>
<a-tooltip v-if="isSharedForm || (!readOnly && isUIAllowed('dataEdit') && !isPublic && !isLocked)" placement="bottom">
<a-tooltip v-if="isSharedForm || (!readOnly && isUIAllowed('dataEdit') && !isPublic)" placement="bottom">
<template #title> {{ $t('title.renameFile') }} </template>
<div class="nc-attachment-download group-hover:(opacity-100) mr-[35px]">

10
packages/nc-gui/components/cell/attachment/index.vue

@ -43,8 +43,6 @@ const sortableRef = ref<HTMLDivElement>()
const currentCellRef = inject(CurrentCellInj, dropZoneInjection.value)
const isLockedMode = inject(IsLockedInj, ref(false))
const isGallery = inject(IsGalleryInj, ref(false))
const isKanban = inject(IsKanbanInj, ref(false))
@ -69,18 +67,14 @@ const {
open: _open,
FileIcon,
selectedImage,
isReadonly: _isReadonly,
isReadonly,
storedFiles,
} = useProvideAttachmentCell(updateModelValue)
const { dragging } = useSortable(sortableRef, visibleItems, updateModelValue, _isReadonly)
const { dragging } = useSortable(sortableRef, visibleItems, updateModelValue, isReadonly)
const active = inject(ActiveCellInj, ref(false))
const isReadonly = computed(() => {
return isLockedMode.value || _isReadonly.value
})
const { state: rowState } = useSmartsheetRowStoreOrThrow()
const { isOverDropZone } = useDropZone(currentCellRef as any, onDrop)

38
packages/nc-gui/components/dashboard/Sidebar/UserInfo.vue

@ -93,17 +93,21 @@ onMounted(() => {
</div>
<template #overlay>
<NcMenu data-testid="nc-sidebar-userinfo">
<NcMenuItem v-e="['c:user:logout']" data-testid="nc-sidebar-user-logout" @click="logout">
<GeneralLoader v-if="isLoggingOut" class="!ml-0.5 !mr-0.5 !max-h-4.5 !-mt-0.5" />
<GeneralIcon v-else icon="signout" class="menu-icon" />
<span class="menu-btn"> {{ $t('general.logout') }}</span>
<NcMenuItem data-testid="nc-sidebar-user-logout" @click="logout">
<div v-e="['c:user:logout']" class="flex gap-2 items-center">
<GeneralLoader v-if="isLoggingOut" class="!ml-0.5 !mr-0.5 !max-h-4.5 !-mt-0.5" />
<GeneralIcon v-else icon="signout" class="menu-icon" />
<span class="menu-btn"> {{ $t('general.logout') }}</span>
</div>
</NcMenuItem>
<template v-if="!isMobileMode">
<NcMenuItem v-e="['c:auth-token:copy']" @click="onCopy">
<GeneralIcon v-if="isAuthTokenCopied" icon="check" class="group-hover:text-black menu-icon" />
<GeneralIcon v-else icon="copy" class="menu-icon" />
<template v-if="isAuthTokenCopied"> {{ $t('title.copiedAuthToken') }} </template>
<template v-else> {{ $t('title.copyAuthToken') }} </template>
<NcMenuItem @click="onCopy">
<div v-e="['c:auth-token:copy']" class="flex gap-2 items-center">
<GeneralIcon v-if="isAuthTokenCopied" icon="check" class="group-hover:text-black menu-icon" />
<GeneralIcon v-else icon="copy" class="menu-icon" />
<template v-if="isAuthTokenCopied"> {{ $t('title.copiedAuthToken') }} </template>
<template v-else> {{ $t('title.copyAuthToken') }} </template>
</div>
</NcMenuItem>
</template>
<NcDivider />
@ -140,13 +144,17 @@ onMounted(() => {
<template v-if="!appInfo.ee">
<NcDivider />
<a-popover key="language" class="lang-menu !py-1.5" placement="rightBottom">
<NcMenuItem v-e="['c:translate:open']">
<GeneralIcon icon="translate" class="group-hover:text-black nc-language ml-0.25 menu-icon" />
{{ $t('labels.language') }}
<div class="flex items-center text-gray-400 text-xs">{{ $t('labels.community.communityTranslated') }}</div>
<div class="flex-1" />
<NcMenuItem>
<div v-e="['c:translate:open']" class="flex gap-2 items-center">
<GeneralIcon icon="translate" class="group-hover:text-black nc-language ml-0.25 menu-icon" />
{{ $t('labels.language') }}
<div class="flex items-center text-gray-400 text-xs">{{ $t('labels.community.communityTranslated') }}</div>
<div class="flex-1" />
<MaterialSymbolsChevronRightRounded class="transform group-hover:(scale-115 text-accent) text-xl text-gray-400" />
<MaterialSymbolsChevronRightRounded
class="transform group-hover:(scale-115 text-accent) text-xl text-gray-400"
/>
</div>
</NcMenuItem>
<template #content>

35
packages/nc-gui/components/dashboard/TreeView/BaseOptions.vue

@ -62,7 +62,6 @@ function openQuickImportDialog(type: string) {
<NcSubMenu class="py-0" data-testid="nc-sidebar-base-import">
<template #title>
<GeneralIcon icon="download" />
{{ $t('labels.importData') }}
</template>
@ -71,41 +70,41 @@ function openQuickImportDialog(type: string) {
<NcMenuItem
v-if="isUIAllowed('airtableImport', { roles: baseRole })"
key="quick-import-airtable"
v-e="['c:import:airtable']"
@click="openAirtableImportDialog(source.base_id, source.id)"
>
<GeneralIcon icon="airtable" class="max-w-3.75 group-hover:text-black" />
<div class="ml-0.5">{{ $t('labels.airtable') }}</div>
<div v-e="['c:import:airtable']" class="flex gap-2 items-center">
<GeneralIcon icon="airtable" class="max-w-3.75 group-hover:text-black" />
<div class="ml-0.5">{{ $t('labels.airtable') }}</div>
</div>
</NcMenuItem>
<NcMenuItem
v-if="isUIAllowed('csvImport', { roles: baseRole })"
key="quick-import-csv"
v-e="['c:import:csv']"
@click="openQuickImportDialog('csv')"
>
<GeneralIcon icon="csv" class="w-4 group-hover:text-black" />
{{ $t('labels.csvFile') }}
<NcMenuItem v-if="isUIAllowed('csvImport', { roles: baseRole })" key="quick-import-csv" @click="openQuickImportDialog('csv')">
<div v-e="['c:import:csv']" class="flex gap-2 items-center">
<GeneralIcon icon="csv" class="w-4 group-hover:text-black" />
{{ $t('labels.csvFile') }}
</div>
</NcMenuItem>
<NcMenuItem
v-if="isUIAllowed('jsonImport', { roles: baseRole })"
key="quick-import-json"
v-e="['c:import:json']"
@click="openQuickImportDialog('json')"
>
<GeneralIcon icon="code" class="w-4 group-hover:text-black" />
{{ $t('labels.jsonFile') }}
<div v-e="['c:import:json']" class="flex gap-2 items-center">
<GeneralIcon icon="code" class="w-4 group-hover:text-black" />
{{ $t('labels.jsonFile') }}
</div>
</NcMenuItem>
<NcMenuItem
v-if="isUIAllowed('excelImport', { roles: baseRole })"
key="quick-import-excel"
v-e="['c:import:excel']"
@click="openQuickImportDialog('excel')"
>
<GeneralIcon icon="excel" class="max-w-4 group-hover:text-black" />
{{ $t('labels.microsoftExcel') }}
<div v-e="['c:import:excel']" class="flex gap-2 items-center">
<GeneralIcon icon="excel" class="max-w-4 group-hover:text-black" />
{{ $t('labels.microsoftExcel') }}
</div>
</NcMenuItem>
</NcSubMenu>
</template>

111
packages/nc-gui/components/dashboard/TreeView/ProjectNode.vue

@ -77,7 +77,7 @@ const tempTitle = ref('')
const activeBaseId = ref('')
const isErdModalOpen = ref<Boolean>(false)
const isErdModalOpen = ref<boolean>(false)
const { t } = useI18n()
@ -116,7 +116,7 @@ const showBaseOption = computed(() => {
return ['airtableImport', 'csvImport', 'jsonImport', 'excelImport'].some((permission) => isUIAllowed(permission))
})
const enableEditMode = () => {
function enableEditMode() {
editMode.value = true
tempTitle.value = base.value.title!
nextTick(() => {
@ -126,7 +126,7 @@ const enableEditMode = () => {
})
}
const updateProjectTitle = async () => {
async function updateProjectTitle() {
if (!tempTitle.value) return
try {
@ -146,7 +146,7 @@ const updateProjectTitle = async () => {
const { copy } = useCopy(true)
const copyProjectInfo = async () => {
async function copyProjectInfo() {
try {
if (
await copy(
@ -168,7 +168,7 @@ defineExpose({
enableEditMode,
})
const setIcon = async (icon: string, base: BaseType) => {
async function setIcon(icon: string, base: BaseType) {
try {
const meta = {
...((base.meta as object) || {}),
@ -224,7 +224,8 @@ function openTableCreateDialog(sourceIndex?: number | undefined) {
}
const isAddNewProjectChildEntityLoading = ref(false)
const addNewProjectChildEntity = async () => {
async function addNewProjectChildEntity() {
if (isAddNewProjectChildEntityLoading.value) return
isAddNewProjectChildEntityLoading.value = true
@ -248,7 +249,7 @@ const addNewProjectChildEntity = async () => {
}
}
const onProjectClick = async (base: NcProject, ignoreNavigation?: boolean, toggleIsExpanded?: boolean) => {
async function onProjectClick(base: NcProject, ignoreNavigation?: boolean, toggleIsExpanded?: boolean) {
if (!base) {
return
}
@ -347,17 +348,17 @@ onKeyStroke('Escape', () => {
const isDuplicateDlgOpen = ref(false)
const selectedProjectToDuplicate = ref()
const duplicateProject = (base: BaseType) => {
function duplicateProject(base: BaseType) {
selectedProjectToDuplicate.value = base
isDuplicateDlgOpen.value = true
}
const tableDelete = () => {
function tableDelete() {
isTableDeleteDialogVisible.value = true
$e('c:table:delete')
}
const projectDelete = () => {
function projectDelete() {
isProjectDeleteDialogVisible.value = true
$e('c:project:delete')
}
@ -396,21 +397,18 @@ const projectDelete = () => {
</NcButton>
<div class="flex items-center mr-1" @click="onProjectClick(base)">
<div class="flex items-center select-none w-6 h-full">
<div v-e="['c:base:emojiSelect']" class="flex items-center select-none w-6 h-full">
<a-spin v-if="base.isLoading" class="!ml-1.25 !flex !flex-row !items-center !my-0.5 w-8" :indicator="indicator" />
<LazyGeneralEmojiPicker
v-else
:key="base.meta?.icon"
v-e="['c:base:emojiSelect']"
:emoji="base.meta?.icon"
:readonly="true"
size="small"
@emoji-selected="setIcon($event, base)"
>
<template #default>
<GeneralProjectIcon :type="base.type" />
</template>
<GeneralProjectIcon :type="base.type" />
</LazyGeneralEmojiPicker>
</div>
</div>
@ -460,24 +458,22 @@ const projectDelete = () => {
@click="isOptionsOpen = false"
>
<template v-if="!isSharedBase">
<NcMenuItem
v-if="isUIAllowed('baseRename')"
v-e="['c:base:rename']"
data-testid="nc-sidebar-project-rename"
@click="enableEditMode"
>
<GeneralIcon icon="edit" class="group-hover:text-black" />
{{ $t('general.rename') }}
<NcMenuItem v-if="isUIAllowed('baseRename')" data-testid="nc-sidebar-project-rename" @click="enableEditMode">
<div v-e="['c:base:rename']" class="flex gap-2 items-center">
<GeneralIcon icon="edit" class="group-hover:text-black" />
{{ $t('general.rename') }}
</div>
</NcMenuItem>
<NcMenuItem
v-if="isUIAllowed('baseDuplicate', { roles: [stringifyRolesObj(orgRoles), baseRole].join() })"
v-e="['c:base:duplicate']"
data-testid="nc-sidebar-base-duplicate"
@click="duplicateProject(base)"
>
<GeneralIcon icon="duplicate" class="text-gray-700" />
{{ $t('general.duplicate') }}
<div v-e="['c:base:duplicate']" class="flex gap-2 items-center">
<GeneralIcon icon="duplicate" class="text-gray-700" />
{{ $t('general.duplicate') }}
</div>
</NcMenuItem>
<NcDivider v-if="['baseDuplicate', 'baseRename'].some((permission) => isUIAllowed(permission))" />
@ -486,40 +482,39 @@ const projectDelete = () => {
<NcMenuItem
v-if="!isEeUI"
key="copy"
v-e="['c:base:copy-proj-info']"
data-testid="nc-sidebar-base-copy-base-info"
@click.stop="copyProjectInfo"
>
<GeneralIcon icon="copy" class="group-hover:text-black" />
{{ $t('activity.account.projInfo') }}
<div v-e="['c:base:copy-proj-info']" class="flex gap-2 items-center">
<GeneralIcon icon="copy" class="group-hover:text-black" />
{{ $t('activity.account.projInfo') }}
</div>
</NcMenuItem>
<!-- ERD View -->
<NcMenuItem
key="erd"
v-e="['c:base:erd']"
data-testid="nc-sidebar-base-relations"
@click="openErdView(base?.sources?.[0]!)"
>
<GeneralIcon icon="erd" />
{{ $t('title.relations') }}
<NcMenuItem key="erd" data-testid="nc-sidebar-base-relations" @click="openErdView(base?.sources?.[0]!)">
<div v-e="['c:base:erd']" class="flex gap-2 items-center">
<GeneralIcon icon="erd" />
{{ $t('title.relations') }}
</div>
</NcMenuItem>
<!-- Swagger: Rest APIs -->
<NcMenuItem
v-if="isUIAllowed('apiDocs')"
key="api"
v-e="['c:base:api-docs']"
data-testid="nc-sidebar-base-rest-apis"
@click.stop="
() => {
$e('c:base:api-docs')
openLink(`/api/v1/db/meta/projects/${base.id}/swagger`, appInfo.ncSiteUrl)
openLink(`/api/v2/meta/bases/${base.id}/swagger`, appInfo.ncSiteUrl)
}
"
>
<GeneralIcon icon="snippet" class="group-hover:text-black !max-w-3.9" />
{{ $t('activity.account.swagger') }}
<div v-e="['c:base:api-docs']" class="flex gap-2 items-center">
<GeneralIcon icon="snippet" class="group-hover:text-black !max-w-3.9" />
{{ $t('activity.account.swagger') }}
</div>
</NcMenuItem>
</template>
@ -533,13 +528,14 @@ const projectDelete = () => {
<NcMenuItem
v-if="isUIAllowed('baseMiscSettings')"
key="teamAndSettings"
v-e="['c:base:settings']"
data-testid="nc-sidebar-base-settings"
class="nc-sidebar-base-base-settings"
@click="toggleDialog(true, 'teamAndAuth', undefined, base.id)"
>
<GeneralIcon icon="settings" class="group-hover:text-black" />
{{ $t('activity.settings') }}
<div v-e="['c:base:settings']" class="flex gap-2 items-center">
<GeneralIcon icon="settings" class="group-hover:text-black" />
{{ $t('activity.settings') }}
</div>
</NcMenuItem>
<NcMenuItem
v-if="isUIAllowed('baseDelete', { roles: [stringifyRolesObj(orgRoles), baseRole].join() })"
@ -547,8 +543,10 @@ const projectDelete = () => {
class="!text-red-500 !hover:bg-red-50"
@click="projectDelete"
>
<GeneralIcon icon="delete" class="w-4" />
{{ $t('general.delete') }}
<div class="flex gap-2 items-center">
<GeneralIcon icon="delete" class="w-4" />
{{ $t('general.delete') }}
</div>
</NcMenuItem>
</NcMenu>
</template>
@ -666,9 +664,11 @@ const projectDelete = () => {
@click="isBasesOptionsOpen[source!.id!] = false"
>
<!-- ERD View -->
<NcMenuItem key="erd" v-e="['c:source:erd']" @click="openErdView(source)">
<GeneralIcon icon="erd" />
{{ $t('title.relations') }}
<NcMenuItem key="erd" @click="openErdView(source)">
<div v-e="['c:source:erd']" class="flex gap-2 items-center">
<GeneralIcon icon="erd" />
{{ $t('title.relations') }}
</div>
</NcMenuItem>
<DashboardTreeViewBaseOptions v-if="showBaseOption" v-model:base="base" :source="source" />
@ -712,12 +712,8 @@ const projectDelete = () => {
<template v-else-if="contextMenuTarget.type === 'source'"></template>
<template v-else-if="contextMenuTarget.type === 'table'">
<NcMenuItem
v-if="isUIAllowed('tableRename')"
v-e="['c:table:rename']"
@click="openRenameTableDialog(contextMenuTarget.value, true)"
>
<div class="nc-base-option-item">
<NcMenuItem v-if="isUIAllowed('tableRename')" @click="openRenameTableDialog(contextMenuTarget.value, true)">
<div v-e="['c:table:rename']" class="nc-base-option-item flex gap-2 items-center">
<GeneralIcon icon="edit" class="text-gray-700" />
{{ $t('general.rename') }}
</div>
@ -725,17 +721,16 @@ const projectDelete = () => {
<NcMenuItem
v-if="isUIAllowed('tableDuplicate') && (contextMenuBase?.is_meta || contextMenuBase?.is_local)"
v-e="['c:table:duplicate']"
@click="duplicateTable(contextMenuTarget.value)"
>
<div class="nc-base-option-item">
<div v-e="['c:table:duplicate']" class="nc-base-option-item flex gap-2 items-center">
<GeneralIcon icon="duplicate" class="text-gray-700" />
{{ $t('general.duplicate') }}
</div>
</NcMenuItem>
<NcDivider />
<NcMenuItem v-if="isUIAllowed('table-delete')" class="!hover:bg-red-50" @click="tableDelete">
<div class="nc-base-option-item text-red-600">
<div class="nc-base-option-item flex gap-2 items-center text-red-600">
<GeneralIcon icon="delete" />
{{ $t('general.delete') }}
</div>

116
packages/nc-gui/components/dashboard/TreeView/TableNode.vue

@ -5,11 +5,12 @@ import { message } from 'ant-design-vue'
import { storeToRefs } from 'pinia'
import { ProjectRoleInj, TreeViewInj, useNuxtApp, useRoles, useTabs } from '#imports'
import type { SidebarTableNode } from '~/lib'
const props = withDefaults(
defineProps<{
base: BaseType
table: TableType
table: SidebarTableNode
sourceIndex: number
}>(),
{ sourceIndex: 0 },
@ -44,7 +45,7 @@ provide(SidebarTableInj, table)
const { setMenuContext, openRenameTableDialog, duplicateTable } = inject(TreeViewInj)!
const { loadViews: _loadViews } = useViewsStore()
const { activeView } = storeToRefs(useViewsStore())
const { activeView, activeViewTitleOrId } = storeToRefs(useViewsStore())
const { isLeftSidebarOpen } = storeToRefs(useSidebarStore())
// todo: temp
@ -135,7 +136,7 @@ watch(
)
const isTableOpened = computed(() => {
return openedTableId.value === table.value?.id && activeView.value?.is_default
return openedTableId.value === table.value?.id && (activeView.value?.is_default || !activeViewTitleOrId.value)
})
</script>
@ -174,14 +175,24 @@ const isTableOpened = computed(() => {
class="nc-sidebar-node-btn nc-sidebar-expand"
@click.stop="onExpand"
>
<GeneralLoader
v-if="table.isViewsLoading"
class="flex w-4 h-4 !text-gray-600 !mt-0.75"
:class="{
'!visible': !isExpanded,
}"
/>
<GeneralIcon
v-else
icon="triangleFill"
class="nc-sidebar-source-node-btns group-hover:visible invisible cursor-pointer transform transition-transform duration-500 h-1.5 w-1.5 !text-gray-600 rotate-90"
:class="{ '!rotate-180': isExpanded }"
/>
</NcButton>
<div class="flex w-auto" :data-testid="`tree-view-table-draggable-handle-${table.title}`">
<div
v-e="['c:table:emoji-picker']"
class="flex items-center nc-table-icon"
:class="{
'pointer-events-none': !canUserEditEmote,
@ -190,7 +201,6 @@ const isTableOpened = computed(() => {
>
<LazyGeneralEmojiPicker
:key="table.meta?.icon"
v-e="['c:table:emoji-picker']"
:emoji="table.meta?.icon"
size="small"
:readonly="!canUserEditEmote || isMobileMode"
@ -239,60 +249,62 @@ const isTableOpened = computed(() => {
</span>
<div class="flex flex-grow h-full"></div>
<div class="flex flex-row items-center">
<NcDropdown
<div
v-if="
!isSharedBase &&
(isUIAllowed('tableRename', { roles: baseRole }) || isUIAllowed('tableDelete', { roles: baseRole }))
"
v-e="['c:table:option']"
:trigger="['click']"
class="nc-sidebar-node-btn"
@click.stop
>
<MdiDotsHorizontal
data-testid="nc-sidebar-table-context-menu"
class="min-w-5.75 min-h-5.75 mt-0.2 mr-0.25 px-0.5 !text-gray-600 transition-opacity opacity-0 group-hover:opacity-100 nc-tbl-context-menu outline-0 rounded-md hover:(bg-gray-500 bg-opacity-15 !text-black)"
/>
<template #overlay>
<NcMenu>
<NcMenuItem
v-if="isUIAllowed('tableRename', { roles: baseRole })"
v-e="['c:table:rename']"
:data-testid="`sidebar-table-rename-${table.title}`"
@click="openRenameTableDialog(table, base.sources[sourceIndex].id)"
>
<GeneralIcon icon="edit" class="text-gray-700" />
{{ $t('general.rename') }}
</NcMenuItem>
<NcMenuItem
v-if="
isUIAllowed('tableDuplicate') &&
base.sources?.[sourceIndex] &&
(base.sources[sourceIndex].is_meta || base.sources[sourceIndex].is_local)
"
v-e="['c:table:duplicate']"
:data-testid="`sidebar-table-duplicate-${table.title}`"
@click="duplicateTable(table)"
>
<GeneralIcon icon="duplicate" class="text-gray-700" />
{{ $t('general.duplicate') }}
</NcMenuItem>
<NcMenuItem
v-if="isUIAllowed('tableDelete', { roles: baseRole })"
v-e="['c:table:delete']"
:data-testid="`sidebar-table-delete-${table.title}`"
class="!text-red-500 !hover:bg-red-50"
@click="isTableDeleteDialogVisible = true"
>
<GeneralIcon icon="delete" />
{{ $t('general.delete') }}
</NcMenuItem>
</NcMenu>
</template>
</NcDropdown>
<NcDropdown :trigger="['click']" class="nc-sidebar-node-btn" @click.stop>
<MdiDotsHorizontal
data-testid="nc-sidebar-table-context-menu"
class="min-w-5.75 min-h-5.75 mt-0.2 mr-0.25 px-0.5 !text-gray-600 transition-opacity opacity-0 group-hover:opacity-100 nc-tbl-context-menu outline-0 rounded-md hover:(bg-gray-500 bg-opacity-15 !text-black)"
/>
<template #overlay>
<NcMenu>
<NcMenuItem
v-if="isUIAllowed('tableRename', { roles: baseRole })"
:data-testid="`sidebar-table-rename-${table.title}`"
@click="openRenameTableDialog(table, base.sources[sourceIndex].id)"
>
<div v-e="['c:table:rename']" class="flex gap-2 items-center">
<GeneralIcon icon="edit" class="text-gray-700" />
{{ $t('general.rename') }}
</div>
</NcMenuItem>
<NcMenuItem
v-if="
isUIAllowed('tableDuplicate') &&
base.sources?.[sourceIndex] &&
(base.sources[sourceIndex].is_meta || base.sources[sourceIndex].is_local)
"
:data-testid="`sidebar-table-duplicate-${table.title}`"
@click="duplicateTable(table)"
>
<div v-e="['c:table:duplicate']" class="flex gap-2 items-center">
<GeneralIcon icon="duplicate" class="text-gray-700" />
{{ $t('general.duplicate') }}
</div>
</NcMenuItem>
<NcMenuItem
v-if="isUIAllowed('tableDelete', { roles: baseRole })"
:data-testid="`sidebar-table-delete-${table.title}`"
class="!text-red-500 !hover:bg-red-50"
@click="isTableDeleteDialogVisible = true"
>
<div v-e="['c:table:delete']" class="flex gap-2 items-center">
<GeneralIcon icon="delete" />
{{ $t('general.delete') }}
</div>
</NcMenuItem>
</NcMenu>
</template>
</NcDropdown>
</div>
</div>
</div>
<DlgTableDelete

8
packages/nc-gui/components/dashboard/TreeView/ViewsNode.vue

@ -192,7 +192,6 @@ watch(isDropdownOpen, async () => {
<template>
<a-menu-item
v-e="['c:view:open']"
class="nc-sidebar-node !min-h-7 !max-h-7 !mb-0.25 select-none group text-gray-700 !flex !items-center !mt-0 hover:(!bg-gray-200 !text-gray-900) cursor-pointer"
:class="{
'!pl-18 !xs:(pl-19.75)': isDefaultBase,
@ -203,9 +202,12 @@ watch(isDropdownOpen, async () => {
@click="onClick"
>
<div v-e="['a:view:open', { view: vModel.type }]" class="text-sm flex items-center w-full gap-1" data-testid="view-item">
<div class="flex min-w-6" :data-testid="`view-sidebar-drag-handle-${vModel.alias || vModel.title}`">
<div
v-e="['c:view:emoji-picker']"
class="flex min-w-6"
:data-testid="`view-sidebar-drag-handle-${vModel.alias || vModel.title}`"
>
<LazyGeneralEmojiPicker
v-e="['c:view:emoji-picker']"
class="nc-table-icon"
:emoji="props.view?.meta?.icon"
size="small"

7
packages/nc-gui/components/dlg/AirtableImport.vue

@ -90,8 +90,10 @@ const onStatus = async (status: JobStatus, data?: any) => {
refreshCommandPalette()
// TODO: add tab of the first table
} else if (status === JobStatus.FAILED) {
await loadTables()
goBack.value = true
pushProgress(data.error.message, status)
refreshCommandPalette()
}
}
@ -115,7 +117,10 @@ const { validateInfos } = useForm(syncSource, validators)
const disableImportButton = computed(() => !syncSource.value.details.apiKey || !syncSource.value.details.syncSourceUrlOrId)
const isLoading = ref(false)
async function saveAndSync() {
isLoading.value = true
await createOrUpdate()
await sync()
}
@ -178,6 +183,7 @@ async function listenForUpdates(id?: string) {
}
} else {
listeningForUpdates.value = false
isLoading.value = false
}
},
)
@ -494,6 +500,7 @@ onMounted(async () => {
v-e="['c:sync-airtable:save-and-sync']"
type="primary"
class="nc-btn-airtable-import"
:loading="isLoading"
:disabled="disableImportButton"
@click="saveAndSync"
>

136
packages/nc-gui/components/dlg/ColumnDuplicate.vue

@ -0,0 +1,136 @@
<script setup lang="ts">
import type { ColumnType } from 'nocodb-sdk'
import { message } from 'ant-design-vue'
import { useVModel } from '#imports'
const props = defineProps<{
modelValue: boolean
column: ColumnType
extra: any
}>()
const emit = defineEmits(['update:modelValue'])
const { api } = useApi()
const dialogShow = useVModel(props, 'modelValue', emit)
const { $e, $poller } = useNuxtApp()
const { activeTable: _activeTable } = storeToRefs(useTablesStore())
const reloadDataHook = inject(ReloadViewDataHookInj)
const { eventBus } = useSmartsheetStoreOrThrow()
const { getMeta } = useMetas()
const meta = inject(MetaInj, ref())
const options = ref({
includeData: true,
})
const optionsToExclude = computed(() => {
const { includeData } = options.value
return {
excludeData: !includeData,
}
})
const isLoading = ref(false)
const reloadTable = async () => {
await getMeta(meta!.value!.id!, true)
eventBus.emit(SmartsheetStoreEvents.FIELD_RELOAD)
reloadDataHook?.trigger()
}
const _duplicate = async () => {
try {
isLoading.value = true
const jobData = await api.dbTable.duplicateColumn(props.column.base_id!, props.column.id!, {
options: optionsToExclude.value,
extra: props.extra,
})
$poller.subscribe(
{ id: jobData.id },
async (data: {
id: string
status?: string
data?: {
error?: {
message: string
}
message?: string
result?: any
}
}) => {
if (data.status !== 'close') {
if (data.status === JobStatus.COMPLETED) {
reloadTable()
isLoading.value = false
dialogShow.value = false
} else if (data.status === JobStatus.FAILED) {
message.error(`There was an error duplicating the column.`)
reloadTable()
isLoading.value = false
dialogShow.value = false
}
}
},
)
$e('a:column:duplicate')
} catch (e: any) {
message.error(await extractSdkResponseErrorMsg(e))
isLoading.value = false
dialogShow.value = false
}
}
onKeyStroke('Enter', () => {
// should only trigger this when our modal is open
if (dialogShow.value) {
_duplicate()
}
})
defineExpose({
duplicate: _duplicate,
})
</script>
<template>
<GeneralModal
v-model:visible="dialogShow"
:class="{ active: dialogShow }"
:closable="!isLoading"
:mask-closable="!isLoading"
:keyboard="!isLoading"
centered
wrap-class-name="nc-modal-column-duplicate"
:footer="null"
class="!w-[30rem]"
@keydown.esc="dialogShow = false"
>
<div>
<div class="prose-xl font-bold self-center">{{ $t('general.duplicate') }} {{ $t('objects.column') }}</div>
<div class="mt-4">Are you sure you want to duplicate the field?</div>
<div class="prose-md self-center text-gray-500 mt-4">{{ $t('title.advancedSettings') }}</div>
<a-divider class="!m-0 !p-0 !my-2" />
<div class="text-xs p-2">
<a-checkbox v-model:checked="options.includeData" :disabled="isLoading">{{ $t('labels.includeData') }}</a-checkbox>
</div>
</div>
<div class="flex flex-row gap-x-2 mt-2.5 pt-2.5 justify-end">
<NcButton v-if="!isLoading" key="back" type="secondary" @click="dialogShow = false">{{ $t('general.cancel') }}</NcButton>
<NcButton key="submit" type="primary" :loading="isLoading" @click="_duplicate">{{ $t('general.confirm') }} </NcButton>
</div>
</GeneralModal>
</template>

16
packages/nc-gui/components/dlg/QuickImport.vue

@ -172,7 +172,9 @@ const disablePreImportButton = computed(() => {
}
})
const disableImportButton = computed(() => !templateEditorRef.value?.isValid)
const isError = ref(false)
const disableImportButton = computed(() => !templateEditorRef.value?.isValid || isError.value)
const disableFormatJsonButton = computed(() => !jsonEditorRef.value?.isValid)
@ -530,6 +532,14 @@ async function parseAndExtractData(val: UploadFile[] | ArrayBuffer | string) {
preImportLoading.value = false
}
}
const onError = () => {
isError.value = true
}
const onChange = () => {
isError.value = false
}
</script>
<template>
@ -558,6 +568,8 @@ async function parseAndExtractData(val: UploadFile[] | ArrayBuffer | string) {
:import-worker="importWorker"
class="nc-quick-import-template-editor"
@import="handleImport"
@error="onError"
@change="onChange"
/>
<a-tabs v-else v-model:activeKey="activeKey" hide-add type="editable-card" tab-position="top">
@ -641,7 +653,7 @@ async function parseAndExtractData(val: UploadFile[] | ArrayBuffer | string) {
<a-form-item v-if="!importDataOnly" class="!my-2">
<a-checkbox v-model:checked="importState.parserConfig.autoSelectFieldTypes">
<span class="caption">Auto-Select Field Types</span>
<span class="caption">{{ $t('labels.autoSelectFieldTypes') }}</span>
</a-checkbox>
</a-form-item>

8
packages/nc-gui/components/dlg/share-and-collaborate/SharePage.vue

@ -16,6 +16,8 @@ const { metas } = useMetas()
const workspaceStore = useWorkspace()
const isLocked = inject(IsLockedInj, ref(false))
const isUpdating = ref({
public: false,
password: false,
@ -269,10 +271,6 @@ function onChangeTheme(color: string) {
const isPublicShared = computed(() => {
return !!activeView.value?.uuid
})
const isPublicShareDisabled = computed(() => {
return false
})
</script>
<template>
@ -286,7 +284,7 @@ const isPublicShareDisabled = computed(() => {
:checked="isPublicShared"
:loading="isUpdating.public"
class="share-view-toggle !mt-0.25"
:disabled="isPublicShareDisabled"
:disabled="isLocked"
@click="toggleShare"
/>
</div>

2
packages/nc-gui/components/general/EmojiPicker.vue

@ -2,7 +2,6 @@
import data from 'emoji-mart-vue-fast/data/apple.json'
import 'emoji-mart-vue-fast/css/emoji-mart.css'
import { Icon } from '@iconify/vue'
import { EmojiIndex, Picker } from 'emoji-mart-vue-fast/src'
const props = defineProps<{
@ -21,6 +20,7 @@ const clearable = computed(() => {
})
const isOpen = ref(false)
const emojiIndex = new EmojiIndex(data, {
emojisToShowFilter: (emoji: any) => {
if (Number(emoji.added_in) >= 14) {

49
packages/nc-gui/components/general/OpenLeftSidebarBtn.vue

@ -11,29 +11,30 @@ const onClick = () => {
</script>
<template>
<NcTooltip
v-e="['c:leftSidebar:hideToggle']"
placement="topLeft"
hide-on-click
class="transition-all duration-150"
:class="{
'opacity-0 w-0 pointer-events-none': !isMobileMode && isLeftSidebarOpen,
'opacity-100 max-w-10': isMobileMode || !isLeftSidebarOpen,
}"
>
<template #title>
{{ isLeftSidebarOpen ? `${$t('title.hideSidebar')}` : `${$t('title.showSidebar')}` }}
</template>
<NcButton
:type="isMobileMode ? 'secondary' : 'text'"
:size="isMobileMode ? 'medium' : 'small'"
class="nc-sidebar-left-toggle-icon !text-gray-600 !hover:text-gray-800 w-8"
@click="onClick"
<div v-e="['c:leftSidebar:hideToggle']">
<NcTooltip
placement="topLeft"
hide-on-click
class="transition-all duration-150"
:class="{
'opacity-0 w-0 pointer-events-none': !isMobileMode && isLeftSidebarOpen,
'opacity-100 max-w-10': isMobileMode || !isLeftSidebarOpen,
}"
>
<div class="flex items-center text-inherit">
<GeneralIcon v-if="isMobileMode" icon="menu" class="text-lg -mt-0.25" />
<GeneralIcon v-else icon="doubleRightArrow" class="duration-150 transition-all !text-lg -mt-0.25" />
</div>
</NcButton>
</NcTooltip>
<template #title>
{{ isLeftSidebarOpen ? `${$t('title.hideSidebar')}` : `${$t('title.showSidebar')}` }}
</template>
<NcButton
:type="isMobileMode ? 'secondary' : 'text'"
:size="isMobileMode ? 'medium' : 'small'"
class="nc-sidebar-left-toggle-icon !text-gray-600 !hover:text-gray-800 w-8"
@click="onClick"
>
<div class="flex items-center text-inherit">
<GeneralIcon v-if="isMobileMode" icon="menu" class="text-lg -mt-0.25" />
<GeneralIcon v-else icon="doubleRightArrow" class="duration-150 transition-all !text-lg -mt-0.25" />
</div>
</NcButton>
</NcTooltip>
</div>
</template>

3
packages/nc-gui/components/nc/Button.vue

@ -172,7 +172,8 @@ useEventListener(NcButton, 'mousedown', () => {
@apply p-0 h-5.75 min-w-5.75 rounded-md;
}
.nc-button.ant-btn[disabled] {
.nc-button.ant-btn[disabled],
.ant-btn-text.nc-button.ant-btn[disabled] {
box-shadow: none !important;
@apply bg-gray-50 border-0 text-gray-300 cursor-not-allowed md:(hover:bg-gray-50);
}

5
packages/nc-gui/components/nc/Switch.vue

@ -11,7 +11,8 @@ const onChange = (e: boolean) => {
</script>
<template>
<a-switch v-model:checked="checked" :disabled="props.disabled" class="nc-switch" size="small" @change="onChange">
<a-switch v-model:checked="checked" :disabled="props.disabled" class="nc-switch" size="small" @change="onChange"> </a-switch>
<span v-if="$slots.default" class="cursor-pointer pl-2" @click="checked = !checked">
<slot />
</a-switch>
</span>
</template>

10
packages/nc-gui/components/smartsheet/Cell.vue

@ -87,8 +87,6 @@ const isGrid = inject(IsGridInj, ref(false))
const isPublic = inject(IsPublicInj, ref(false))
const isLocked = inject(IsLockedInj, ref(false))
const isSurveyForm = inject(IsSurveyFormInj, ref(false))
const isEditColumnMenu = inject(EditColumnInj, ref(false))
@ -216,7 +214,7 @@ onUnmounted(() => {
>
<template v-if="column">
<template v-if="intersected">
<LazyCellTextArea v-if="isTextArea(column)" v-model="vModel" />
<LazyCellTextArea v-if="isTextArea(column)" v-model="vModel" :virtual="props.virtual" />
<LazyCellGeoData v-else-if="isGeoData(column)" v-model="vModel" />
<LazyCellCheckbox v-else-if="isBoolean(column, abstractType)" v-model="vModel" />
<LazyCellAttachment v-else-if="isAttachment(column)" v-model="vModel" :row-index="props.rowIndex" />
@ -255,11 +253,7 @@ onUnmounted(() => {
<LazyCellJson v-else-if="isJSON(column)" v-model="vModel" />
<LazyCellText v-else v-model="vModel" />
<div
v-if="
(isLocked || (isPublic && readOnly && !isForm) || isSystemColumn(column)) &&
!isAttachment(column) &&
!isTextArea(column)
"
v-if="(isPublic && readOnly && !isForm) || (isSystemColumn(column) && !isAttachment(column) && !isTextArea(column))"
class="nc-locked-overlay"
/>
</template>

33
packages/nc-gui/components/smartsheet/Form.vue

@ -48,6 +48,8 @@ const formState = reactive({})
const secondsRemain = ref(0)
const isLocked = inject(IsLockedInj, ref(false))
const isEditable = isUIAllowed('viewFieldEdit' as Permission)
const meta = inject(MetaInj, ref())
@ -347,6 +349,8 @@ watch(submitted, (v) => {
})
function handleMouseUp(col: Record<string, any>, hiddenColIndex: number) {
if (isLocked.value) return
if (!moved.value) {
const index = localColumns.value.length
col.order = (index ? localColumns.value[index - 1].order : 0) + 1
@ -378,6 +382,12 @@ watch(view, (nextView) => {
reloadEventHook.trigger()
}
})
const onFormItemClick = (element: any) => {
if (isLocked.value) return
activeRow.value = element.title
}
</script>
<template>
@ -427,6 +437,7 @@ watch(view, (nextView) => {
type="secondary"
class="nc-form-add-all"
data-testid="nc-form-add-all"
:disabled="isLocked"
@click="addAllColumns"
>
<!-- Add all -->
@ -438,6 +449,7 @@ watch(view, (nextView) => {
type="secondary"
class="nc-form-remove-all"
data-testid="nc-form-remove-all"
:disabled="isLocked"
@click="removeAllColumns"
>
<!-- Remove all -->
@ -451,6 +463,7 @@ watch(view, (nextView) => {
item-key="id"
draggable=".item"
group="form-inputs"
:disabled="isLocked"
class="flex flex-col gap-2"
@start="drag = true"
@end="drag = false"
@ -459,6 +472,9 @@ watch(view, (nextView) => {
<a-card
size="small"
class="!border-0 color-transition cursor-pointer item hover:(bg-primary ring-1 ring-accent ring-opacity-100) bg-opacity-10 !rounded !shadow-lg"
:class="{
'!bg-gray-50 !hover:bg-gray-50 !hover:ring-transparent !cursor-not-allowed': isLocked,
}"
:data-testid="`nc-form-hidden-column-${element.label || element.title}`"
@mousedown="moved = false"
@mousemove="moved = false"
@ -484,7 +500,7 @@ watch(view, (nextView) => {
</a-card>
</template>
<template #footer>
<template v-if="!isLocked" #footer>
<div
class="my-4 select-none border-dashed border-2 border-gray-400 py-3 text-gray-400 text-center nc-drag-n-drop-to-hide"
data-testid="nc-drag-n-drop-to-hide"
@ -553,6 +569,7 @@ watch(view, (nextView) => {
autosize
size="large"
hide-details
:disabled="isLocked"
placeholder="Form Title"
:bordered="false"
data-testid="nc-form-heading"
@ -580,7 +597,7 @@ watch(view, (nextView) => {
hide-details
:placeholder="$t('msg.info.formDesc')"
:bordered="false"
:disabled="!isEditable"
:disabled="!isEditable || isLocked"
data-testid="nc-form-sub-heading"
@blur="updateView"
@click="updateView"
@ -598,6 +615,7 @@ watch(view, (nextView) => {
group="form-inputs"
class="h-full"
:move="onMoveCallback"
:disabled="isLocked"
@change="onMove($event)"
@start="drag = true"
@end="drag = false"
@ -610,12 +628,15 @@ watch(view, (nextView) => {
{
'bg-primary bg-opacity-5 ring-0.5 ring-accent ring-opacity-100': activeRow === element.title,
},
{
'!hover:bg-white !ring-0 !cursor-auto': isLocked,
},
]"
data-testid="nc-form-fields"
@click="activeRow = element.title"
@click="onFormItemClick(element)"
>
<div
v-if="isUIAllowed('viewFieldEdit') && !isRequired(element, element.required)"
v-if="isUIAllowed('viewFieldEdit') && !isRequired(element, element.required) && !isLocked"
class="absolute flex top-2 right-2"
>
<component
@ -795,9 +816,9 @@ watch(view, (nextView) => {
</a-card>
</a-form>
<a-divider />
<a-divider v-if="!isLocked" />
<div v-if="isEditable" class="px-4 flex flex-col gap-2">
<div v-if="isEditable && !isLocked" class="px-4 flex flex-col gap-2">
<!-- After form is submitted -->
<div class="text-lg text-gray-700">
{{ $t('msg.info.afterFormSubmitted') }}

8
packages/nc-gui/components/smartsheet/Pagination.vue

@ -48,15 +48,15 @@ const size = computed(() => vPaginationData.value?.pageSize ?? 25)
const page = computed({
get: () => vPaginationData?.value?.page ?? 1,
set: async (p) => {
isViewDataLoading.value = true
isPaginationLoading.value = true
try {
await changePage?.(p)
isViewDataLoading.value = false
isPaginationLoading.value = false
} catch (e) {
if (axios.isCancel(e)) {
return
}
isViewDataLoading.value = false
isPaginationLoading.value = false
}
},
})
@ -100,7 +100,7 @@ const renderAltOrOptlKey = () => {
'ml-8': alignLeft,
}"
>
<div v-if="isPaginationLoading" class="flex flex-row justify-center item-center min-h-10 min-w-42">
<div v-if="isViewDataLoading" class="flex flex-row justify-center item-center min-h-10 min-w-42">
<a-skeleton :active="true" :title="true" :paragraph="false" class="-mt-1 max-w-60" />
</div>
<NcPagination

2
packages/nc-gui/components/smartsheet/Toolbar.vue

@ -39,7 +39,7 @@ const { allowCSVDownload } = useSharedView()
<!-- <LazySmartsheetToolbarQrScannerButton v-if="isMobileMode && (isGrid || isKanban || isGallery)" /> -->
<LazySmartsheetToolbarExport v-if="(!isPublic && !isUIAllowed('dataInsert')) || (isPublic && allowCSVDownload)" />
<LazySmartsheetToolbarExport v-if="isPublic && allowCSVDownload" />
<div class="flex-1" />
</template>

7
packages/nc-gui/components/smartsheet/VirtualCell.vue

@ -31,6 +31,7 @@ const props = defineProps<{
modelValue: any
row?: Row
active?: boolean
readOnly?: boolean
}>()
const emit = defineEmits(['update:modelValue', 'navigate', 'save'])
@ -38,12 +39,14 @@ const emit = defineEmits(['update:modelValue', 'navigate', 'save'])
const column = toRef(props, 'column')
const active = toRef(props, 'active', false)
const row = toRef(props, 'row')
const readOnly = toRef(props, 'readOnly', false)
provide(ColumnInj, column)
provide(ActiveCellInj, active)
provide(RowInj, row)
provide(CellValueInj, toRef(props, 'modelValue'))
provide(SaveRowInj, () => emit('save'))
provide(ReadonlyInj, readOnly)
const isGrid = inject(IsGridInj, ref(false))
@ -94,7 +97,9 @@ onUnmounted(() => {
<div
ref="elementToObserve"
class="nc-virtual-cell w-full flex items-center"
:class="{ 'text-right justify-end': isGrid && !isForm && isRollup(column) && !isExpandedForm }"
:class="{
'text-right justify-end': isGrid && !isForm && isRollup(column) && !isExpandedForm,
}"
@keydown.enter.exact="onNavigate(NavigateDir.NEXT, $event)"
@keydown.shift.enter.exact="onNavigate(NavigateDir.PREV, $event)"
>

6
packages/nc-gui/components/smartsheet/column/DecimalOptions.vue

@ -34,7 +34,11 @@ onMounted(() => {
<template>
<a-form-item :label="$t('placeholder.precision')">
<a-select v-model:value="vModel.meta.precision" dropdown-class-name="nc-dropdown-decimal-format">
<a-select
v-if="vModel.meta?.precision"
v-model:value="vModel.meta.precision"
dropdown-class-name="nc-dropdown-decimal-format"
>
<a-select-option v-for="(format, i) of precisionFormats" :key="i" :value="format">
<div class="flex flex-row items-center">
<div class="text-xs">

123
packages/nc-gui/components/smartsheet/column/EditOrAdd.vue

@ -37,6 +37,7 @@ const props = defineProps<{
hideType?: boolean
hideAdditionalOptions?: boolean
fromTableExplorer?: boolean
readonly?: boolean
}>()
const emit = defineEmits(['submit', 'cancel', 'mounted', 'add', 'update'])
@ -66,6 +67,8 @@ const isForm = inject(IsFormInj, ref(false))
const isKanban = inject(IsKanbanInj, ref(false))
const readOnly = computed(() => props.readonly)
const { isMysql, isMssql, isXcdbBase } = useBase()
const reloadDataTrigger = inject(ReloadViewDataHookInj)
@ -114,6 +117,8 @@ const reloadMetaAndData = async () => {
const saving = ref(false)
async function onSubmit() {
if (readOnly.value) return
saving.value = true
const saved = await addOrUpdate(reloadMetaAndData, props.columnPosition)
saving.value = false
@ -134,7 +139,7 @@ async function onSubmit() {
// focus and select the column name field
const antInput = ref()
watchEffect(() => {
if (antInput.value && formState.value) {
if (antInput.value && formState.value && !readOnly.value) {
// todo: replace setTimeout
setTimeout(() => {
// focus and select input only if active element is not an input or textarea
@ -215,9 +220,10 @@ if (props.fromTableExplorer) {
:class="{
'bg-white': !props.fromTableExplorer,
'w-[400px]': !props.embedMode,
'!w-146': isTextArea(formState) && formState.meta.richMode,
'!w-[600px]': formState.uidt === UITypes.Formula && !props.embedMode,
'!w-[500px]': formState.uidt === UITypes.Attachment && !props.embedMode && !appInfo.ee,
'shadow-lg border-1 border-gray-50 shadow-gray-100 rounded-md p-6': !embedMode,
'shadow-lg border-1 border-gray-100 shadow-gray-300 rounded-xl p-6': !embedMode,
}"
@keydown="handleEscape"
@click.stop
@ -232,6 +238,7 @@ if (props.fromTableExplorer) {
<input
ref="antInput"
v-model="formState.title"
:disabled="readOnly"
class="flex flex-grow nc-fields-input text-lg font-bold outline-none bg-inherit"
:contenteditable="true"
/>
@ -247,7 +254,7 @@ if (props.fromTableExplorer) {
ref="antInput"
v-model:value="formState.title"
class="nc-column-name-input !rounded !mt-1"
:disabled="isKanban"
:disabled="isKanban || readOnly"
@input="onAlter(8)"
/>
</a-form-item>
@ -263,7 +270,7 @@ if (props.fromTableExplorer) {
v-model:value="formState.uidt"
show-search
class="nc-column-type-input !rounded"
:disabled="isKanban"
:disabled="isKanban || readOnly"
dropdown-class-name="nc-dropdown-column-type "
@change="onUidtOrIdTypeChange"
@dblclick="showDeprecated = !showDeprecated"
@ -285,28 +292,32 @@ if (props.fromTableExplorer) {
</div> -->
</div>
<LazySmartsheetColumnFormulaOptions v-if="formState.uidt === UITypes.Formula" v-model:value="formState" />
<LazySmartsheetColumnQrCodeOptions v-if="formState.uidt === UITypes.QrCode" v-model="formState" />
<LazySmartsheetColumnBarcodeOptions v-if="formState.uidt === UITypes.Barcode" v-model="formState" />
<LazySmartsheetColumnCurrencyOptions v-if="formState.uidt === UITypes.Currency" v-model:value="formState" />
<LazySmartsheetColumnDurationOptions v-if="formState.uidt === UITypes.Duration" v-model:value="formState" />
<LazySmartsheetColumnRatingOptions v-if="formState.uidt === UITypes.Rating" v-model:value="formState" />
<LazySmartsheetColumnCheckboxOptions v-if="formState.uidt === UITypes.Checkbox" v-model:value="formState" />
<LazySmartsheetColumnLookupOptions v-if="formState.uidt === UITypes.Lookup" v-model:value="formState" />
<LazySmartsheetColumnDateOptions v-if="formState.uidt === UITypes.Date" v-model:value="formState" />
<LazySmartsheetColumnDecimalOptions v-if="formState.uidt === UITypes.Decimal" v-model:value="formState" />
<LazySmartsheetColumnDateTimeOptions v-if="formState.uidt === UITypes.DateTime" v-model:value="formState" />
<LazySmartsheetColumnRollupOptions v-if="formState.uidt === UITypes.Rollup" v-model:value="formState" />
<LazySmartsheetColumnLinkedToAnotherRecordOptions
v-if="!isEdit && (formState.uidt === UITypes.LinkToAnotherRecord || formState.uidt === UITypes.Links)"
v-model:value="formState"
/>
<LazySmartsheetColumnLinkOptions v-if="isEdit && formState.uidt === UITypes.Links" v-model:value="formState" />
<LazySmartsheetColumnSpecificDBTypeOptions v-if="formState.uidt === UITypes.SpecificDBType" />
<SmartsheetColumnSelectOptions
v-if="formState.uidt === UITypes.SingleSelect || formState.uidt === UITypes.MultiSelect"
v-model:value="formState"
/>
<template v-if="!readOnly">
<LazySmartsheetColumnFormulaOptions v-if="formState.uidt === UITypes.Formula" v-model:value="formState" />
<LazySmartsheetColumnQrCodeOptions v-if="formState.uidt === UITypes.QrCode" v-model="formState" />
<LazySmartsheetColumnBarcodeOptions v-if="formState.uidt === UITypes.Barcode" v-model="formState" />
<LazySmartsheetColumnCurrencyOptions v-if="formState.uidt === UITypes.Currency" v-model:value="formState" />
<LazySmartsheetColumnLongTextOptions v-if="formState.uidt === UITypes.LongText" v-model:value="formState" />
<LazySmartsheetColumnDurationOptions v-if="formState.uidt === UITypes.Duration" v-model:value="formState" />
<LazySmartsheetColumnRatingOptions v-if="formState.uidt === UITypes.Rating" v-model:value="formState" />
<LazySmartsheetColumnCheckboxOptions v-if="formState.uidt === UITypes.Checkbox" v-model:value="formState" />
<LazySmartsheetColumnLookupOptions v-if="formState.uidt === UITypes.Lookup" v-model:value="formState" />
<LazySmartsheetColumnDateOptions v-if="formState.uidt === UITypes.Date" v-model:value="formState" />
<LazySmartsheetColumnDecimalOptions v-if="formState.uidt === UITypes.Decimal" v-model:value="formState" />
<LazySmartsheetColumnDateTimeOptions v-if="formState.uidt === UITypes.DateTime" v-model:value="formState" />
<LazySmartsheetColumnRollupOptions v-if="formState.uidt === UITypes.Rollup" v-model:value="formState" />
<LazySmartsheetColumnLinkedToAnotherRecordOptions
v-if="!isEdit && (formState.uidt === UITypes.LinkToAnotherRecord || formState.uidt === UITypes.Links)"
:key="formState.uidt"
v-model:value="formState"
/>
<LazySmartsheetColumnLinkOptions v-if="isEdit && formState.uidt === UITypes.Links" v-model:value="formState" />
<LazySmartsheetColumnSpecificDBTypeOptions v-if="formState.uidt === UITypes.SpecificDBType" />
<SmartsheetColumnSelectOptions
v-if="formState.uidt === UITypes.SingleSelect || formState.uidt === UITypes.MultiSelect"
v-model:value="formState"
/>
</template>
</div>
<a-checkbox
v-if="formState.meta && columnToValidate.includes(formState.uidt)"
@ -317,41 +328,47 @@ if (props.fromTableExplorer) {
{{ `${$t('msg.acceptOnlyValid')} ${formState.uidt}` }}
</span>
</a-checkbox>
<div class="!my-3">
<!--
Default Value for JSON & LongText is not supported in MySQL
Default Value is Disabled for MSSQL -->
<LazySmartsheetColumnDefaultValue
v-if="
<template v-if="!readOnly">
<div class="!my-3">
<!--
Default Value for JSON & LongText is not supported in MySQL
Default Value is Disabled for MSSQL -->
<LazySmartsheetColumnRichLongTextDefaultValue
v-if="isTextArea(formState) && formState.meta.richMode"
v-model:value="formState"
/>
<LazySmartsheetColumnDefaultValue
v-else-if="
!isVirtualCol(formState) &&
!isAttachment(formState) &&
!isMssql(meta!.source_id) &&
!(isMysql(meta!.source_id) && (isJSON(formState) || isTextArea(formState)))
"
v-model:value="formState"
/>
</div>
<div
v-if="!props.hideAdditionalOptions && !isVirtualCol(formState.uidt) && (!appInfo.ee || (appInfo.ee && !isXcdbBase(meta!.source_id) && formState.uidt === UITypes.SpecificDBType))"
class="text-xs cursor-pointer text-gray-400 nc-more-options mb-1 mt-4 flex items-center gap-1 justify-end"
@click="advancedOptions = !advancedOptions"
>
{{ advancedOptions ? $t('general.hideAll') : $t('general.showMore') }}
<component :is="advancedOptions ? MdiMinusIcon : MdiPlusIcon" />
</div>
<Transition name="layout" mode="out-in">
<div v-if="advancedOptions" class="overflow-hidden">
<LazySmartsheetColumnAttachmentOptions v-if="appInfo.ee && isAttachment(formState)" v-model:value="formState" />
<LazySmartsheetColumnAdvancedOptions
v-if="formState.uidt !== UITypes.Attachment"
v-model:value="formState"
:advanced-db-options="advancedOptions || formState.uidt === UITypes.SpecificDBType"
/>
</div>
</Transition>
<div
v-if="!props.hideAdditionalOptions && !isVirtualCol(formState.uidt) && (!appInfo.ee || (appInfo.ee && !isXcdbBase(meta!.source_id) && formState.uidt === UITypes.SpecificDBType))"
class="text-xs cursor-pointer text-gray-400 nc-more-options mb-1 mt-4 flex items-center gap-1 justify-end"
@click="advancedOptions = !advancedOptions"
>
{{ advancedOptions ? $t('general.hideAll') : $t('general.showMore') }}
<component :is="advancedOptions ? MdiMinusIcon : MdiPlusIcon" />
</div>
<Transition name="layout" mode="out-in">
<div v-if="advancedOptions" class="overflow-hidden">
<LazySmartsheetColumnAttachmentOptions v-if="appInfo.ee && isAttachment(formState)" v-model:value="formState" />
<LazySmartsheetColumnAdvancedOptions
v-if="formState.uidt !== UITypes.Attachment"
v-model:value="formState"
:advanced-db-options="advancedOptions || formState.uidt === UITypes.SpecificDBType"
/>
</div>
</Transition>
</template>
<template v-if="props.fromTableExplorer">
<a-form-item></a-form-item>

4
packages/nc-gui/components/smartsheet/column/FormulaOptions.vue

@ -112,7 +112,7 @@ const validators = {
const availableFunctions = formulaList
const availableBinOps = ['+', '-', '*', '/', '>', '<', '==', '<=', '>=', '!=']
const availableBinOps = ['+', '-', '*', '/', '>', '<', '==', '<=', '>=', '!=', '&']
const autocomplete = ref(false)
@ -472,7 +472,7 @@ function validateAgainstType(parsedTree: any, expectedType: string, func: any, t
}
if (col.uidt === UITypes.Formula) {
const foundType = getRootDataType(jsep((col as any).formula_raw))
const foundType = getRootDataType(jsep(col.colOptions?.formula_raw))
if (foundType === 'N/A') {
typeErrors.add(t('msg.formula.notSupportedToReferenceColumn', { columnName: col.title }))
} else if (expectedType !== foundType) {

38
packages/nc-gui/components/smartsheet/column/LongTextOptions.vue

@ -0,0 +1,38 @@
<!-- File not in use for now -->
<script setup lang="ts">
import { useVModel } from '#imports'
const props = defineProps<{
value: any
}>()
const emit = defineEmits(['update:value'])
const vModel = useVModel(props, 'value', emit)
const richMode = computed({
get: () => vModel.value.meta?.richMode,
set: (value) => {
if (!vModel.value.meta) vModel.value.meta = {}
vModel.value.meta.richMode = value
},
})
watch(richMode, () => {
vModel.value.cdf = null
})
</script>
<template>
<div class="flex flex-col mt-2 gap-2">
<a-form-item>
<div class="flex flex-row items-center">
<NcSwitch v-model:checked="richMode" :name="$t('labels.enableRichText')" size="small">
<div class="text-xs">{{ $t('labels.enableRichText') }}</div>
</NcSwitch>
</div>
</a-form-item>
</div>
</template>

26
packages/nc-gui/components/smartsheet/column/RichLongTextDefaultValue.vue

@ -0,0 +1,26 @@
<script lang="ts" setup>
const props = defineProps<{
value: any
}>()
const emits = defineEmits(['update:value'])
const vModel = useVModel(props, 'value', emits)
const cdfValue = computed({
get: () => vModel.value.cdf,
set: (value) => {
vModel.value.cdf = value
},
})
</script>
<template>
<div>
<div class="!my-3 text-xs">{{ $t('placeholder.defaultValue') }}</div>
<div class="flex flex-row gap-2">
<div class="border-1 relative pt-11 flex items-center w-full px-0 my-[-4px] border-gray-300 rounded-md !max-h-70 !pb-2.5">
<LazyCellRichText v-model:value="cdfValue" class="border-t-1 border-gray-100" show-menu full-mode />
</div>
</div>
</div>
</template>

48
packages/nc-gui/components/smartsheet/column/SelectOptions.vue

@ -29,7 +29,7 @@ const { optionsMagic: _optionsMagic } = useNocoEe()
const optionsWrapperDomRef = ref<HTMLElement>()
const options = ref<(Option & { status?: 'remove' })[]>([])
const options = ref<(Option & { status?: 'remove'; index?: number })[]>([])
const isAddingOption = ref(false)
@ -38,7 +38,7 @@ const OPTIONS_PAGE_COUNT = 20
const loadedOptionAnchor = ref(OPTIONS_PAGE_COUNT)
const isReverseLazyLoad = ref(false)
const renderedOptions = ref<(Option & { status?: 'remove' })[]>([])
const renderedOptions = ref<(Option & { status?: 'remove'; index?: number })[]>([])
const savedDefaultOption = ref<Option | null>(null)
const savedCdf = ref<string | null>(null)
@ -98,6 +98,12 @@ onMounted(() => {
options.value = vModel.value.colOptions.options
let indexCounter = 0
options.value.map((el) => {
el.index = indexCounter++
return el
})
loadedOptionAnchor.value = Math.min(loadedOptionAnchor.value, options.value.length)
renderedOptions.value = [...options.value].slice(0, loadedOptionAnchor.value)
@ -107,7 +113,7 @@ onMounted(() => {
op.title = op.title.replace(/^'/, '').replace(/'$/, '')
}
if (vModel.value.cdf) {
if (vModel.value.cdf && typeof vModel.value.cdf === 'string') {
const fndDefaultOption = options.value.find((el) => el.title === vModel.value.cdf)
if (!fndDefaultOption) {
vModel.value.cdf = vModel.value.cdf.replace(/^'/, '').replace(/'$/, '')
@ -135,6 +141,7 @@ const addNewOption = () => {
const tempOption = {
title: '',
color: getNextColor(),
index: options.value.length,
}
options.value.push(tempOption)
@ -168,11 +175,30 @@ const addNewOption = () => {
// }
const syncOptions = () => {
vModel.value.colOptions.options = renderedOptions.value.filter((op) => op.status !== 'remove')
vModel.value.colOptions.options = options.value
.filter((op) => op.status !== 'remove')
.sort((a, b) => {
const renderA = renderedOptions.value.findIndex((el) => a.index !== undefined && el.index === a.index)
const renderB = renderedOptions.value.findIndex((el) => a.index !== undefined && el.index === b.index)
if (renderA === -1 || renderB === -1) return 0
return renderA - renderB
})
.map((op) => {
const { index: _i, status: _s, ...rest } = op
return rest
})
}
const removeRenderedOption = (index: number) => {
renderedOptions.value[index].status = 'remove'
const renderedOption = renderedOptions.value[index]
if (renderedOption.index === undefined || isNaN(renderedOption.index)) return
const option = options.value[renderedOption.index]
renderedOption.status = 'remove'
option.status = 'remove'
syncOptions()
const optionId = renderedOptions.value[index]?.id
@ -193,7 +219,15 @@ const optionChanged = (changedId: string) => {
}
const undoRemoveRenderedOption = (index: number) => {
renderedOptions.value[index].status = undefined
const renderedOption = renderedOptions.value[index]
if (renderedOption.index === undefined || isNaN(renderedOption.index)) return
const option = options.value[renderedOption.index]
renderedOption.status = undefined
option.status = undefined
syncOptions()
const optionId = renderedOptions.value[index]?.id
@ -215,7 +249,7 @@ const undoRemoveRenderedOption = (index: number) => {
// Removes the Select Option from cdf if the option is removed
watch(vModel.value, (next) => {
const cdfs = (next.cdf ?? '').split(',')
const cdfs = (next.cdf ?? '').toString().split(',')
const values = (next.colOptions.options ?? []).map((col) => {
return col.title.replace(/^'/, '').replace(/'$/, '')
})

102
packages/nc-gui/components/smartsheet/details/Fields.vue

@ -1,7 +1,7 @@
<script setup lang="ts">
import { diff } from 'deep-object-diff'
import { message } from 'ant-design-vue'
import { UITypes, isSystemColumn } from 'nocodb-sdk'
import { UITypes, isSystemColumn, isVirtualCol } from 'nocodb-sdk'
import Draggable from 'vuedraggable'
import { onKeyDown, useMagicKeys } from '@vueuse/core'
import type { ColumnType, SelectOptionsType } from 'nocodb-sdk'
@ -40,6 +40,8 @@ const { getMeta } = useMetas()
const { meta, view } = useSmartsheetStoreOrThrow()
const isLocked = inject(IsLockedInj, ref(false))
const { openedViewsTab } = storeToRefs(useViewsStore())
const moveOps = ref<moveOp[]>([])
@ -587,6 +589,8 @@ const toggleVisibility = async (checked: boolean, field: Field) => {
useEventListener(document, 'keydown', async (e: KeyboardEvent) => {
const cmdOrCtrl = isMac() ? e.metaKey : e.ctrlKey
if (isLocked.value) return
if (cmdOrCtrl && e.key.toLowerCase() === 's') {
if (openedViewsTab.value !== 'field') return
e.preventDefault()
@ -625,7 +629,11 @@ onKeyDown('ArrowUp', () => {
})
onKeyDown('Delete', () => {
if (isLocked.value) return
if (document.activeElement?.tagName === 'INPUT') return
if (document.activeElement?.tagName === 'TEXTAREA') return
const isDeletedField = fieldStatus(activeField.value) === 'delete'
if (!isDeletedField && activeField.value) {
onFieldDelete(activeField.value)
@ -633,7 +641,11 @@ onKeyDown('Delete', () => {
})
onKeyDown('Backspace', () => {
if (isLocked.value) return
if (document.activeElement?.tagName === 'INPUT') return
if (document.activeElement?.tagName === 'TEXTAREA') return
const isDeletedField = fieldStatus(activeField.value) === 'delete'
if (!isDeletedField && activeField.value) {
onFieldDelete(activeField.value)
@ -641,7 +653,7 @@ onKeyDown('Backspace', () => {
})
onKeyDown('ArrowRight', () => {
if (document.activeElement?.tagName === 'INPUT') return
if (document.activeElement?.tagName === 'TEXTAREA') return
if (activeField.value) {
const input = document.querySelector('.nc-fields-input')
if (input) {
@ -659,11 +671,15 @@ const onClickCopyFieldUrl = async (field: ColumnType) => {
const keys = useMagicKeys()
whenever(keys.meta_s, () => {
if (isLocked.value) return
if (!meta.value?.id) return
if (openedViewsTab.value === 'field') saveChanges()
})
whenever(keys.ctrl_s, () => {
if (isLocked.value) return
if (!meta.value?.id) return
if (openedViewsTab.value === 'field') saveChanges()
})
@ -718,9 +734,9 @@ const onFieldOptionUpdate = () => {
</template>
</a-input>
<div class="flex gap-2">
<NcTooltip>
<NcTooltip :disabled="isLocked">
<template #title> {{ `${renderAltOrOptlKey()} + C` }} </template>
<NcButton type="secondary" size="small" class="mr-1" :disabled="loading" @click="addField()">
<NcButton type="secondary" size="small" class="mr-1" :disabled="loading || isLocked" @click="addField()">
<div class="flex items-center gap-2">
<GeneralIcon icon="plus" class="w-3" />
New Field
@ -730,19 +746,22 @@ const onFieldOptionUpdate = () => {
<NcButton
type="secondary"
size="small"
:disabled="!loading && ops.length < 1 && moveOps.length < 1 && visibilityOps.length < 1"
:disabled="(!loading && ops.length < 1 && moveOps.length < 1 && visibilityOps.length < 1) || isLocked"
@click="clearChanges()"
>
Reset
</NcButton>
<NcTooltip>
<NcTooltip :disabled="isLocked">
<template #title> {{ `${renderCmdOrCtrlKey()} + S` }} </template>
<NcButton
type="primary"
size="small"
:loading="loading"
:disabled="isColumnsValid ? !loading && ops.length < 1 && moveOps.length < 1 && visibilityOps.length < 1 : true"
:disabled="
(isColumnsValid ? !loading && ops.length < 1 && moveOps.length < 1 && visibilityOps.length < 1 : true) ||
isLocked
"
@click="saveChanges()"
>
Save changes
@ -752,7 +771,7 @@ const onFieldOptionUpdate = () => {
</div>
<div class="flex flex-row rounded-lg border-1 border-gray-200">
<div ref="fieldsListWrapperDomRef" class="nc-scrollbar-md !overflow-auto w-full flex-grow-1 nc-fields-height">
<Draggable v-model="fields" item-key="id" @change="onMove($event)">
<Draggable v-model="fields" :disabled="isLocked" item-key="id" @change="onMove($event)">
<template #item="{ element: field }">
<div
v-if="field.title.toLowerCase().includes(searchQuery.toLowerCase()) && !field.pv"
@ -761,9 +780,16 @@ const onFieldOptionUpdate = () => {
@click="changeField(field, $event)"
>
<div class="flex items-center flex-1 py-2.5 gap-1 w-2/6">
<component :is="iconMap.drag" class="cursor-move !h-3.75 text-gray-600 mr-1" />
<component
:is="iconMap.drag"
class="cursor-move !h-3.75 text-gray-600 mr-1"
:class="{
'opacity-0 !cursor-default': isLocked,
}"
/>
<NcCheckbox
v-if="field.id && viewFieldsMap[field.id]"
:disabled="isLocked"
:checked="
visibilityOps.find((op) => op.column.fk_column_id === field.id)?.visible ?? viewFieldsMap[field.id].show
"
@ -774,8 +800,15 @@ const onFieldOptionUpdate = () => {
"
/>
<NcCheckbox v-else :disabled="true" class="opacity-0" :checked="true" />
<SmartsheetHeaderVirtualCellIcon
v-if="field && isVirtualCol(fieldState(field) || field)"
:column-meta="fieldState(field) || field"
:class="{
'text-brand-500': compareCols(field, activeField),
}"
/>
<SmartsheetHeaderCellIcon
v-if="field"
v-else
:column-meta="fieldState(field) || field"
:class="{
'text-brand-500': compareCols(field, activeField),
@ -875,27 +908,29 @@ const onFieldOptionUpdate = () => {
</NcButton>
</div>
</NcTooltip>
<a-menu-divider class="my-1.5" />
<a-menu-divider v-if="!isLocked" class="my-1.5" />
</template>
<NcMenuItem key="table-explorer-duplicate" @click="duplicateField(field)">
<Icon class="iconify text-gray-800" icon="lucide:copy" /><span>Duplicate</span>
</NcMenuItem>
<NcMenuItem v-if="!field.pv" key="table-explorer-insert-above" @click="addField(field, true)">
<Icon class="iconify text-gray-800" icon="lucide:arrow-up" /><span>Insert above</span>
</NcMenuItem>
<NcMenuItem key="table-explorer-insert-below" @click="addField(field)">
<Icon class="iconify text-gray-800" icon="lucide:arrow-down" /><span>Insert below</span>
</NcMenuItem>
<a-menu-divider class="my-1.5" />
<NcMenuItem key="table-explorer-delete" class="!hover:bg-red-50" @click="onFieldDelete(field)">
<div class="text-red-500">
<GeneralIcon icon="delete" class="group-hover:text-accent -ml-0.25 -mt-0.75 mr-0.5" />
Delete
</div>
</NcMenuItem>
<template v-if="!isLocked">
<NcMenuItem key="table-explorer-duplicate" @click="duplicateField(field)">
<Icon class="iconify text-gray-800" icon="lucide:copy" /><span>Duplicate</span>
</NcMenuItem>
<NcMenuItem v-if="!field.pv" key="table-explorer-insert-above" @click="addField(field, true)">
<Icon class="iconify text-gray-800" icon="lucide:arrow-up" /><span>Insert above</span>
</NcMenuItem>
<NcMenuItem key="table-explorer-insert-below" @click="addField(field)">
<Icon class="iconify text-gray-800" icon="lucide:arrow-down" /><span>Insert below</span>
</NcMenuItem>
<a-menu-divider class="my-1.5" />
<NcMenuItem key="table-explorer-delete" class="!hover:bg-red-50" @click="onFieldDelete(field)">
<div class="text-red-500">
<GeneralIcon icon="delete" class="group-hover:text-accent -ml-0.25 -mt-0.75 mr-0.5" />
Delete
</div>
</NcMenuItem>
</template>
</NcMenu>
</template>
</NcDropdown>
@ -920,7 +955,13 @@ const onFieldOptionUpdate = () => {
@click="changeField(displayColumn, $event)"
>
<div class="flex items-center flex-1 py-2.5 gap-1 w-2/6">
<component :is="iconMap.drag" class="cursor-move !h-3.75 text-gray-200 mr-1" />
<component
:is="iconMap.drag"
class="cursor-move !h-3.75 text-gray-200 mr-1"
:class="{
'opacity-0 !cursor-default': isLocked,
}"
/>
<NcCheckbox :disabled="true" :checked="true" />
<SmartsheetHeaderCellIcon
v-if="displayColumn"
@ -1039,6 +1080,7 @@ const onFieldOptionUpdate = () => {
:preload="fieldState(activeField)"
:table-explorer-columns="fields"
embed-mode
:readonly="isLocked"
from-table-explorer
@update="onFieldUpdate"
@add="onFieldAdd"

4
packages/nc-gui/components/smartsheet/expanded-form/Comments.vue

@ -5,7 +5,7 @@ import { Icon } from '@iconify/vue'
import { ref, timeAgo, useExpandedFormStoreOrThrow, useGlobal, useRoles, watch } from '#imports'
const props = defineProps<{
isLoading: boolean
loading: boolean
}>()
const { loadCommentsAndLogs, commentsAndLogs, saveComment: _saveComment, comment, updateComment } = useExpandedFormStoreOrThrow()
@ -16,7 +16,7 @@ const commentsWrapperEl = ref<HTMLDivElement>()
const { user, appInfo } = useGlobal()
const isExpandedFormLoading = computed(() => props.isLoading)
const isExpandedFormLoading = computed(() => props.loading)
const tab = ref<'comments' | 'audits'>('comments')

38
packages/nc-gui/components/smartsheet/expanded-form/index.vue

@ -41,11 +41,13 @@ interface Props {
showNextPrevIcons?: boolean
firstRow?: boolean
lastRow?: boolean
closeAfterSave?: boolean
newRecordHeader?: string
}
const props = defineProps<Props>()
const emits = defineEmits(['update:modelValue', 'cancel', 'next', 'prev'])
const emits = defineEmits(['update:modelValue', 'cancel', 'next', 'prev', 'createdRecord'])
const { activeView } = storeToRefs(useViewsStore())
@ -86,6 +88,8 @@ const isRecordLinkCopied = ref(false)
const { isUIAllowed } = useRoles()
const readOnly = computed(() => !isUIAllowed('dataEdit') || isPublic.value)
const reloadTrigger = inject(ReloadRowDataHookInj, createEventHook())
const { addOrEditStackRow } = useKanbanViewStoreOrThrow()
@ -198,9 +202,17 @@ const save = async () => {
await _save(undefined, undefined, {
kanbanClbk,
})
_loadRow()
reloadTrigger?.trigger()
}
isUnsavedFormExist.value = false
if (props.closeAfterSave) {
isExpanded.value = false
}
emits('createdRecord', _row.value.row)
}
const isPreventChangeModalOpen = ref(false)
@ -486,12 +498,17 @@ export default {
<div v-if="isLoading">
<a-skeleton-input class="!h-8 !sm:mr-14 !w-52 mt-1 !rounded-md !overflow-hidden" active size="small" />
</div>
<div
v-if="row.rowMeta?.new || props.newRecordHeader"
class="flex items-center truncate font-bold text-gray-800 text-xl"
>
{{ props.newRecordHeader ?? $t('activity.newRecord') }}
</div>
<div v-else-if="displayValue && !row.rowMeta?.new" class="flex items-center font-bold text-gray-800 text-xl w-64">
<span class="truncate">
{{ displayValue }}
</span>
</div>
<div v-if="row.rowMeta?.new" class="flex items-center truncate font-bold text-gray-800 text-xl">New Record</div>
</div>
<div class="flex gap-2">
<NcButton
@ -543,14 +560,15 @@ export default {
<NcDivider v-if="isUIAllowed('dataEdit') && !isNew" />
<NcMenuItem
v-if="isUIAllowed('dataEdit') && !isNew"
v-e="['c:row-expand:delete']"
class="!text-red-500 !hover:bg-red-50"
@click="!isNew && onDeleteRowClick()"
>
<component :is="iconMap.delete" data-testid="nc-expanded-form-delete" class="cursor-pointer nc-delete-row" />
<span class="-ml-0.5">
{{ $t('activity.deleteRecord') }}
</span>
<div v-e="['c:row-expand:delete']" data-testid="nc-expanded-form-delete" class="flex gap-2 items-center">
<component :is="iconMap.delete" class="cursor-pointer nc-delete-row" />
<span class="-ml-0.25">
{{ $t('activity.deleteRecord') }}
</span>
</div>
</NcMenuItem>
</NcMenu>
</template>
@ -653,6 +671,7 @@ export default {
:class="{
'px-1': isReadOnlyVirtualCell(col),
}"
:read-only="readOnly"
/>
<LazySmartsheetCell
@ -661,7 +680,7 @@ export default {
:column="col"
:edit-enabled="true"
:active="true"
:read-only="isPublic"
:read-only="readOnly"
@update:model-value="changedColumns.add(col.title)"
/>
</SmartsheetDivDataCell>
@ -721,6 +740,7 @@ export default {
v-model="_row.row[col.title]"
:row="_row"
:column="col"
:read-only="readOnly"
/>
<LazySmartsheetCell
@ -729,7 +749,7 @@ export default {
:column="col"
:edit-enabled="true"
:active="true"
:read-only="isPublic"
:read-only="readOnly"
@update:model-value="changedColumns.add(col.title)"
/>
</LazySmartsheetDivDataCell>

39
packages/nc-gui/components/smartsheet/grid/GroupBy.vue

@ -1,8 +1,10 @@
<script lang="ts" setup>
import tinycolor from 'tinycolor2'
import { UITypes } from 'nocodb-sdk'
import Table from './Table.vue'
import GroupBy from './GroupBy.vue'
import GroupByTable from './GroupByTable.vue'
import GroupByLabel from './GroupByLabel.vue'
import { GROUP_BY_VARS, computed, ref } from '#imports'
import type { Group, Row } from '#imports'
@ -134,6 +136,27 @@ const onScroll = (e: Event) => {
if (!vGroup.value.root) return
_scrollLeft.value = (e.target as HTMLElement).scrollLeft
}
// a method to parse group key if grouped column type is LTAR or Lookup
// in these 2 scenario it will return json array or `___` separated value
const parseKey = (group) => {
const key = group.key.toString()
// parse json array key if it's a lookup or link to another record
if ((key && group.column?.uidt === UITypes.Lookup) || group.column?.uidt === UITypes.LinkToAnotherRecord) {
try {
const parsedKey = JSON.parse(key)
return parsedKey
} catch {
// if parsing try to split it by `___` (for sqlite)
return key.split('___')
}
}
return [key]
}
const shouldRenderCell = (column) =>
[UITypes.Lookup, UITypes.Attachment, UITypes.Barcode, UITypes.QrCode, UITypes.Links].includes(column?.uidt)
</script>
<template>
@ -227,6 +250,15 @@ const onScroll = (e: Event) => {
</span>
</a-tag>
</template>
<div
v-else-if="!(grp.key in GROUP_BY_VARS.VAR_TITLES) && shouldRenderCell(grp.column)"
class="flex min-w-[100px] flex-wrap"
>
<template v-for="(val, ind) of parseKey(grp)" :key="ind">
<GroupByLabel v-if="val" :column="grp.column" :model-value="val" />
<span v-else class="text-gray-400">No mapped value</span>
</template>
</div>
<a-tag
v-else
:key="`panel-tag-${grp.column.id}-${grp.key}`"
@ -247,7 +279,12 @@ const onScroll = (e: Event) => {
'font-weight': 500,
}"
>
{{ grp.key in GROUP_BY_VARS.VAR_TITLES ? GROUP_BY_VARS.VAR_TITLES[grp.key] : grp.key }}
<template v-if="grp.key in GROUP_BY_VARS.VAR_TITLES">{{
GROUP_BY_VARS.VAR_TITLES[grp.key]
}}</template>
<template v-else>
{{ parseKey(grp)?.join(', ') }}
</template>
</span>
</a-tag>
</div>

28
packages/nc-gui/components/smartsheet/grid/GroupByLabel.vue

@ -0,0 +1,28 @@
<script setup lang="ts">
import type { ColumnType } from 'nocodb-sdk'
import { isVirtualCol } from 'nocodb-sdk'
defineProps<{
column: ColumnType
modelValue: any
}>()
provide(ReadonlyInj, true)
</script>
<template>
<div class="pointer-events-none">
<LazySmartsheetRow :row="{ row: { [column.title]: modelValue }, rowMeta: {} }">
<LazySmartsheetVirtualCell v-if="isVirtualCol(column)" :model-value="modelValue" class="!text-gray-600" :column="column" />
<LazySmartsheetCell
v-else
:model-value="modelValue"
class="!text-gray-600"
:column="column"
:edit-enabled="false"
:read-only="true"
/>
</LazySmartsheetRow>
</div>
</template>

239
packages/nc-gui/components/smartsheet/grid/Table.vue

@ -142,7 +142,12 @@ const { getMeta } = useMetas()
const { addUndo, clone, defineViewScope } = useUndoRedo()
const { isViewColumnsLoading, updateGridViewColumn, gridViewCols, resizingColOldWith } = useViewColumnsOrThrow()
const {
isViewColumnsLoading: _isViewColumnsLoading,
updateGridViewColumn,
gridViewCols,
resizingColOldWith,
} = useViewColumnsOrThrow()
const { isExpandedFormCommentMode } = storeToRefs(useConfigStore())
@ -179,9 +184,11 @@ const fillHandle = ref<HTMLElement>()
const gridRect = useElementBounding(gridWrapper)
const isViewColumnsLoading = computed(() => _isViewColumnsLoading.value || !meta.value)
// #Permissions
const { isUIAllowed } = useRoles()
const hasEditPermission = computed(() => isUIAllowed('dataEdit') && !isLocked.value)
const hasEditPermission = computed(() => isUIAllowed('dataEdit'))
const isAddingColumnAllowed = computed(() => !readOnly.value && !isLocked.value && isUIAllowed('fieldAdd') && !isSqlView.value)
const { onDrag, onDragStart, draggedCol, dragColPlaceholderDomRef, toBeDroppedColId } = useColumnDrag({
@ -344,7 +351,7 @@ async function clearCell(ctx: { row: number; col: number } | null, skipUpdate =
}
function makeEditable(row: Row, col: ColumnType) {
if (!hasEditPermission.value || editEnabled.value || isView || isLocked.value || readOnly.value || isSystemColumn(col)) {
if (!hasEditPermission.value || editEnabled.value || isView || readOnly.value || isSystemColumn(col)) {
return
}
@ -375,9 +382,7 @@ function makeEditable(row: Row, col: ColumnType) {
// #Computed
const isAddingEmptyRowAllowed = computed(
() => !isView && !isLocked.value && hasEditPermission.value && !isSqlView.value && !isPublicView.value,
)
const isAddingEmptyRowAllowed = computed(() => !isView && hasEditPermission.value && !isSqlView.value && !isPublicView.value)
const visibleColLength = computed(() => fields.value?.length)
@ -409,7 +414,9 @@ const dummyRowDataForLoading = computed(() => {
})
const showSkeleton = computed(
() => disableSkeleton !== true && (isViewDataLoading.value || isPaginationLoading.value || isViewColumnsLoading.value),
() =>
(disableSkeleton !== true && (isViewDataLoading.value || isPaginationLoading.value || isViewColumnsLoading.value)) ||
!meta.value,
)
// #Grid
@ -443,9 +450,7 @@ async function openNewRecordHandler() {
}
const onDraftRecordClick = () => {
if (!isLocked?.value) {
openNewRecordFormHook.trigger()
}
openNewRecordFormHook.trigger()
}
const onNewRecordToGridClick = () => {
@ -552,6 +557,8 @@ const {
return true
}
if (isExpandedCellInputExist()) return
// skip keyboard event handling if there is a drawer / modal
if (isDrawerOrModalExist()) {
return true
@ -560,7 +567,9 @@ const {
const cmdOrCtrl = isMac() ? e.metaKey : e.ctrlKey
const altOrOptionKey = e.altKey
if (e.key === ' ') {
if (isCellActive.value && !editEnabled.value && hasEditPermission.value && activeCell.row !== null) {
const isRichModalOpen = isExpandedCellInputExist()
if (isCellActive.value && !editEnabled.value && hasEditPermission.value && activeCell.row !== null && !isRichModalOpen) {
e.preventDefault()
const row = dataRef.value[activeCell.row]
expandForm?.(row)
@ -756,6 +765,9 @@ onClickOutside(tableBodyEl, (e) => {
if (activeCell.row === null || activeCell.col === null) return
const isRichModalOpen = isExpandedCellInputExist()
if (isRichModalOpen) return
const activeCol = fields.value[activeCell.col]
if (editEnabled.value && (isVirtualCol(activeCol) || activeCol.uidt === UITypes.JSON)) return
@ -978,7 +990,6 @@ const refreshFillHandle = () => {
const showFillHandle = computed(
() =>
!readOnly.value &&
!isLocked.value &&
!editEnabled.value &&
(!selectedRange.isEmpty() || (activeCell.row !== null && activeCell.col !== null)) &&
!dataRef.value[(isNaN(selectedRange.end.row) ? activeCell.row : selectedRange.end.row) ?? -1]?.rowMeta?.new,
@ -1057,14 +1068,18 @@ useEventListener(document, 'mouseup', () => {
/** handle keypress events */
useEventListener(document, 'keydown', async (e: KeyboardEvent) => {
if (e.key === 'Alt') {
const isRichModalOpen = isExpandedCellInputExist()
if (e.key === 'Alt' && !isRichModalOpen) {
altModifier.value = true
}
})
/** handle keypress events */
useEventListener(document, 'keyup', async (e: KeyboardEvent) => {
if (e.key === 'Alt') {
const isRichModalOpen = isExpandedCellInputExist()
if (e.key === 'Alt' && !isRichModalOpen) {
altModifier.value = false
disableUrlOverlay.value = false
}
@ -1111,22 +1126,6 @@ onBeforeUnmount(async () => {
reloadViewDataHook?.on(reloadViewDataHandler)
openNewRecordFormHook?.on(openNewRecordHandler)
// TODO: Use CSS animations
const showLoaderAfterDelay = ref(false)
watch([isViewDataLoading, showSkeleton, isPaginationLoading], () => {
if (!isViewDataLoading.value && !showSkeleton.value && !isPaginationLoading.value) {
showLoaderAfterDelay.value = false
return
}
showLoaderAfterDelay.value = false
setTimeout(() => {
showLoaderAfterDelay.value = true
}, 500)
})
// #Watchers
// reset context menu target on hide
@ -1217,7 +1216,7 @@ const handleCellClick = (event: MouseEvent, row: number, col: number) => {
}
const loaderText = computed(() => {
if (isViewDataLoading.value) {
if (isPaginationLoading.value) {
if (paginationDataRef.value?.totalRows && paginationDataRef.value?.pageSize) {
return `Loading page<br/>${paginationDataRef.value.page} of ${Math.ceil(
paginationDataRef.value?.totalRows / paginationDataRef.value?.pageSize,
@ -1256,10 +1255,7 @@ onKeyStroke('ArrowDown', onDown)
></div>
</div>
<div ref="gridWrapper" class="nc-grid-wrapper min-h-0 flex-1 relative" :class="gridWrapperClass">
<div
v-show="showSkeleton && !isPaginationLoading && showLoaderAfterDelay"
class="flex items-center justify-center absolute l-0 t-0 w-full h-full z-10 pb-10"
>
<div v-show="isPaginationLoading" class="flex items-center justify-center absolute l-0 t-0 w-full h-full z-10 pb-10">
<div class="flex flex-col justify-center gap-2">
<GeneralLoader size="xlarge" />
<span class="text-center" v-html="loaderText"></span>
@ -1270,7 +1266,7 @@ onKeyStroke('ArrowDown', onDown)
:trigger="isSqlView ? [] : ['contextmenu']"
overlay-class-name="nc-dropdown-grid-context-menu"
>
<div class="table-overlay" :class="{ 'nc-grid-skelton-loader': showSkeleton }">
<div class="table-overlay" :class="{ 'nc-grid-skeleton-loader': showSkeleton }">
<table
ref="smartTable"
class="xc-row-table nc-grid backgroundColorDefault !h-auto bg-white relative"
@ -1471,15 +1467,10 @@ onKeyStroke('ArrowDown', onDown)
></td>
</tr>
</template>
<LazySmartsheetRow
v-for="(row, rowIndex) of dataRef"
v-show="!showSkeleton"
ref="rowRefs"
:key="rowIndex"
:row="row"
>
<LazySmartsheetRow v-for="(row, rowIndex) of dataRef" ref="rowRefs" :key="rowIndex" :row="row">
<template #default="{ state }">
<tr
v-show="!showSkeleton"
class="nc-grid-row !xs:h-14"
:style="{ height: rowHeight ? `${rowHeight * 1.8}rem` : `1.8rem` }"
:data-testid="`grid-row-${rowIndex}`"
@ -1492,7 +1483,7 @@ onKeyStroke('ArrowDown', onDown)
>
<div class="items-center flex gap-1 min-w-[60px]">
<div
v-if="!readOnly || !isLocked || isMobileMode"
v-if="!readOnly || isMobileMode"
class="nc-row-no sm:min-w-4 text-xs text-gray-500"
:class="{ toggle: !readOnly, hidden: row.rowMeta.selected }"
>
@ -1518,29 +1509,28 @@ onKeyStroke('ArrowDown', onDown)
class="!flex items-center"
:data-testid="`row-save-spinner-${rowIndex}`"
/>
<template v-else-if="!isLocked">
<span
v-if="row.rowMeta?.commentCount && expandForm"
v-e="['c:expanded-form:open']"
class="py-1 px-3 rounded-full text-xs cursor-pointer select-none transform hover:(scale-110)"
:style="{ backgroundColor: enumColor.light[row.rowMeta.commentCount % enumColor.light.length] }"
<span
v-if="row.rowMeta?.commentCount && expandForm"
v-e="['c:expanded-form:open']"
class="py-1 px-3 rounded-full text-xs cursor-pointer select-none transform hover:(scale-110)"
:style="{ backgroundColor: enumColor.light[row.rowMeta.commentCount % enumColor.light.length] }"
@click="expandAndLooseFocus(row, state)"
>
{{ row.rowMeta.commentCount }}
</span>
<div
v-else-if="!row.rowMeta.saving"
class="cursor-pointer flex items-center border-1 border-gray-100 active:ring rounded p-1 hover:(bg-gray-50)"
>
<component
:is="iconMap.expand"
v-if="expandForm"
v-e="['c:row-expand:open']"
class="select-none transform hover:(text-black scale-120) nc-row-expand"
@click="expandAndLooseFocus(row, state)"
>
{{ row.rowMeta.commentCount }}
</span>
<div
v-else
class="cursor-pointer flex items-center border-1 border-gray-100 active:ring rounded p-1 hover:(bg-gray-50)"
>
<component
:is="iconMap.expand"
v-if="expandForm"
v-e="['c:row-expand:open']"
class="select-none transform hover:(text-black scale-120) nc-row-expand"
@click="expandAndLooseFocus(row, state)"
/>
</div>
</template>
/>
</div>
</div>
</div>
</td>
@ -1658,50 +1648,53 @@ onKeyStroke('ArrowDown', onDown)
<NcMenu class="!rounded !py-0" @click="contextMenu = false">
<NcMenuItem
v-if="isEeUI && !contextMenuClosing && !contextMenuTarget && data.some((r) => r.rowMeta.selected)"
v-e="['a:row:update-bulk']"
@click="emits('bulkUpdateDlg')"
>
<component :is="iconMap.edit" />
{{ $t('title.updateSelectedRows') }}
<div v-e="['a:row:update-bulk']" class="flex gap-2 items-center">
<component :is="iconMap.edit" />
{{ $t('title.updateSelectedRows') }}
</div>
</NcMenuItem>
<NcMenuItem
v-if="!contextMenuClosing && !contextMenuTarget && data.some((r) => r.rowMeta.selected)"
v-e="['a:row:delete-bulk']"
class="nc-base-menu-item !text-red-600 !hover:bg-red-50"
data-testid="nc-delete-row"
@click="deleteSelectedRows"
>
<component :is="iconMap.delete" />
<!-- Delete Selected Rows -->
{{ $t('activity.deleteSelectedRow') }}
<div v-e="['a:row:delete-bulk']" class="flex gap-2 items-center">
<component :is="iconMap.delete" />
<!-- Delete Selected Rows -->
{{ $t('activity.deleteSelectedRow') }}
</div>
</NcMenuItem>
<!-- <NcMenuItem -->
<!-- v-if="contextMenuTarget && selectedRange.isSingleCell()" -->
<!-- v-e="['a:row:insert']" -->
<!-- class="nc-base-menu-item" -->
<!-- @click="addEmptyRow(contextMenuTarget.row + 1)" -->
<!-- > -->
<!-- <GeneralIcon icon="plus" /> -->
<!-- Insert New Row -->
<!-- {{ $t('activity.insertRow') }} -->
<!-- </NcMenuItem> -->
<!-- <NcMenuItem -->
<!-- v-if="contextMenuTarget && selectedRange.isSingleCell()" -->
<!-- class="nc-base-menu-item" -->
<!-- @click="addEmptyRow(contextMenuTarget.row + 1)" -->
<!-- > -->
<!-- <div v-e="['a:row:insert']" class="flex gap-2 items-center"> -->
<!-- <GeneralIcon icon="plus" /> -->
<!-- Insert New Row -->
<!-- {{ $t('activity.insertRow') }} -->
<!-- </div> -->
<!-- </NcMenuItem> -->
<NcMenuItem
v-if="contextMenuTarget"
v-e="['a:row:copy']"
class="nc-base-menu-item"
data-testid="context-menu-item-copy"
@click="copyValue(contextMenuTarget)"
>
<GeneralIcon icon="copy" />
<!-- Copy -->
{{ $t('general.copy') }}
<div v-e="['a:row:copy']" class="flex gap-2 items-center">
<GeneralIcon icon="copy" />
<!-- Copy -->
{{ $t('general.copy') }}
</div>
</NcMenuItem>
<!-- Clear cell -->
<!-- Clear cell -->
<NcMenuItem
v-if="
contextMenuTarget &&
@ -1709,58 +1702,62 @@ onKeyStroke('ArrowDown', onDown)
selectedRange.isSingleCell() &&
(isLinksOrLTAR(fields[contextMenuTarget.col]) || !isVirtualCol(fields[contextMenuTarget.col]))
"
v-e="['a:row:clear']"
class="nc-base-menu-item"
@click="clearCell(contextMenuTarget)"
>
<GeneralIcon icon="close" />
{{ $t('general.clear') }}
<div v-e="['a:row:clear']" class="flex gap-2 items-center">
<GeneralIcon icon="close" />
{{ $t('general.clear') }}
</div>
</NcMenuItem>
<!-- Clear cell -->
<!-- Clear cell -->
<NcMenuItem
v-else-if="contextMenuTarget && hasEditPermission"
v-e="['a:row:clear-range']"
class="nc-base-menu-item"
@click="clearSelectedRangeOfCells()"
>
<GeneralIcon icon="closeBox" class="text-gray-500" />
{{ $t('general.clear') }}
<div v-e="['a:row:clear-range']" class="flex gap-2 items-center">
<GeneralIcon icon="closeBox" class="text-gray-500" />
{{ $t('general.clear') }}
</div>
</NcMenuItem>
<template
v-if="contextMenuTarget && !isLocked && selectedRange.isSingleCell() && isUIAllowed('commentEdit') && !isMobileMode"
<NcDivider />
<NcMenuItem
v-if="contextMenuTarget && selectedRange.isSingleCell() && isUIAllowed('commentEdit') && !isMobileMode"
class="nc-base-menu-item"
@click="commentRow(contextMenuTarget.row)"
>
<NcDivider />
<NcMenuItem v-e="['a:row:comment']" class="nc-base-menu-item" @click="commentRow(contextMenuTarget.row)">
<div v-e="['a:row:comment']" class="flex gap-2 items-center">
<MdiMessageOutline class="h-4 w-4" />
{{ $t('general.comment') }}
</NcMenuItem>
</template>
</div>
</NcMenuItem>
<template v-if="hasEditPermission">
<NcDivider v-if="!(!contextMenuClosing && !contextMenuTarget && data.some((r) => r.rowMeta.selected))" />
<NcMenuItem
v-if="contextMenuTarget && (selectedRange.isSingleCell() || selectedRange.isSingleRow())"
v-e="['a:row:delete']"
class="nc-base-menu-item !text-red-600 !hover:bg-red-50"
@click="confirmDeleteRow(contextMenuTarget.row)"
>
<GeneralIcon icon="delete" />
<!-- Delete Row -->
{{ $t('activity.deleteRow') }}
<div v-e="['a:row:delete']" class="flex gap-2 items-center">
<GeneralIcon icon="delete" />
<!-- Delete Row -->
{{ $t('activity.deleteRow') }}
</div>
</NcMenuItem>
<div v-else-if="contextMenuTarget && deleteRangeOfRows">
<NcMenuItem
v-e="['a:row:delete']"
class="nc-base-menu-item !text-red-600 !hover:bg-red-50"
@click="deleteSelectedRangeOfRows"
>
<NcMenuItem
v-else-if="contextMenuTarget && deleteRangeOfRows"
class="nc-base-menu-item !text-red-600 !hover:bg-red-50"
@click="deleteSelectedRangeOfRows"
>
<div v-e="['a:row:delete']" class="flex gap-2 items-center">
<GeneralIcon icon="delete" class="text-gray-500 text-red-600" />
<!-- Delete Rows -->
{{ $t('activity.deleteRows') }}
</NcMenuItem>
</div>
</div>
</NcMenuItem>
</template>
</NcMenu>
</template>
@ -1780,7 +1777,7 @@ onKeyStroke('ArrowDown', onDown)
:extra-style="paginationStyleRef?.extraStyle"
>
<template #add-record>
<div v-if="isAddingEmptyRowAllowed" class="flex ml-1">
<div v-if="isAddingEmptyRowAllowed && !showSkeleton && !isPaginationLoading" class="flex ml-1">
<NcButton
v-if="isMobileMode"
v-e="[isAddNewRecordGridMode ? 'c:row:add:grid' : 'c:row:add:form']"
@ -1816,8 +1813,7 @@ onKeyStroke('ArrowDown', onDown)
>
<div
v-e="['c:row:add:grid']"
:class="{ 'group': !isLocked, 'disabled-ring': isLocked }"
class="px-4 py-3 flex flex-col select-none gap-y-2 cursor-pointer hover:bg-gray-100 text-gray-600 nc-new-record-with-grid"
class="px-4 py-3 flex flex-col select-none gap-y-2 cursor-pointer hover:bg-gray-100 text-gray-600 nc-new-record-with-grid group"
@click="onNewRecordToGridClick"
>
<div class="flex flex-row items-center justify-between w-full">
@ -1833,8 +1829,7 @@ onKeyStroke('ArrowDown', onDown)
</div>
<div
v-e="['c:row:add:form']"
:class="{ 'group': !isLocked, 'disabled-ring': isLocked }"
class="px-4 py-3 flex flex-col select-none gap-y-2 cursor-pointer hover:bg-gray-100 text-gray-600 nc-new-record-with-form"
class="px-4 py-3 flex flex-col select-none gap-y-2 cursor-pointer hover:bg-gray-100 text-gray-600 nc-new-record-with-form group"
@click="onNewRecordToFormClick"
>
<div class="flex flex-row items-center justify-between w-full">
@ -2000,7 +1995,7 @@ onKeyStroke('ArrowDown', onDown)
}
}
.nc-grid-skelton-loader {
.nc-grid-skeleton-loader {
thead th:nth-child(2) {
@apply border-r-1 !border-r-gray-50;
}

8
packages/nc-gui/components/smartsheet/grid/usePaginationShortcuts.ts

@ -26,6 +26,8 @@ const usePaginationShortcuts = ({
}
const onLeft = async (e: KeyboardEvent) => {
if (isExpandedCellInputExist()) return
if (!e.altKey) return
e.preventDefault()
@ -36,6 +38,8 @@ const usePaginationShortcuts = ({
}
const onRight = async (e: KeyboardEvent) => {
if (isExpandedCellInputExist()) return
if (!e.altKey) return
e.preventDefault()
@ -47,6 +51,8 @@ const usePaginationShortcuts = ({
}
const onDown = async (e: KeyboardEvent) => {
if (isExpandedCellInputExist()) return
if (!e.altKey) return
e.preventDefault()
@ -56,6 +62,8 @@ const usePaginationShortcuts = ({
}
const onUp = async (e: KeyboardEvent) => {
if (isExpandedCellInputExist()) return
if (!e.altKey) return
e.preventDefault()

6
packages/nc-gui/components/smartsheet/header/Cell.vue

@ -17,6 +17,8 @@ const hideMenu = toRef(props, 'hideMenu')
const isForm = inject(IsFormInj, ref(false))
const isLocked = inject(IsLockedInj, ref(false))
const isSurveyForm = inject(IsSurveyFormInj, ref(false))
const isExpandedForm = inject(IsExpandedFormOpenInj, ref(false))
@ -46,12 +48,16 @@ const closeAddColumnDropdown = () => {
}
const openHeaderMenu = () => {
if (isLocked.value) return
if (!isForm.value && !isExpandedForm.value && isUIAllowed('fieldEdit') && !isMobileMode.value) {
editColumnDropdown.value = true
}
}
const openDropDown = (e: Event) => {
if (isLocked.value) return
if (isForm.value || isExpandedForm.value || (!isUIAllowed('fieldEdit') && !isMobileMode.value)) return
e.preventDefault()

8
packages/nc-gui/components/smartsheet/header/CellIcon.ts

@ -103,7 +103,9 @@ export default defineComponent({
setup(props) {
const columnMeta = toRef(props, 'columnMeta')
const column = inject(ColumnInj, columnMeta)
const injectedColumn = inject(ColumnInj, columnMeta)
const column = computed(() => columnMeta.value ?? injectedColumn.value)
const { sqlUis } = storeToRefs(useBase())
@ -112,9 +114,9 @@ export default defineComponent({
const abstractType = computed(() => column.value && sqlUi.value.getAbstractType(column.value))
return () => {
if (!column.value) return null
if (!column.value && !columnMeta.value) return null
return h(renderIcon(column.value, abstractType.value), {
return h(renderIcon((columnMeta.value ?? column.value)!, abstractType.value), {
class: 'text-inherit mx-1',
})
}

106
packages/nc-gui/components/smartsheet/header/Menu.vue

@ -8,8 +8,6 @@ import {
MetaInj,
ReloadViewDataHookInj,
SmartsheetStoreEvents,
extractSdkResponseErrorMsg,
getUniqueColumnName,
iconMap,
inject,
message,
@ -112,48 +110,24 @@ const sortByColumn = async (direction: 'asc' | 'desc') => {
})
}
const duplicateColumn = async () => {
const isDuplicateDlgOpen = ref(false)
const selectedColumnExtra = ref<any>()
const duplicateDialogRef = ref<any>()
const duplicateVirtualColumn = async () => {
let columnCreatePayload = {}
// generate duplicate column name
const duplicateColumnName = getUniqueColumnName(`${column!.value.title}_copy`, meta!.value!.columns!)
// construct column create payload
switch (column?.value.uidt) {
case UITypes.LinkToAnotherRecord:
case UITypes.Links:
case UITypes.Lookup:
case UITypes.Rollup:
case UITypes.Formula:
return message.info('Not available at the moment')
case UITypes.SingleSelect:
case UITypes.MultiSelect:
columnCreatePayload = {
...column!.value!,
title: duplicateColumnName,
column_name: duplicateColumnName,
id: undefined,
order: undefined,
colOptions: {
options:
column.value.colOptions?.options?.map((option: Record<string, any>) => ({
...option,
id: undefined,
})) ?? [],
},
}
break
default:
columnCreatePayload = {
...column!.value!,
...(column!.value.colOptions ?? {}),
title: duplicateColumnName,
column_name: duplicateColumnName,
id: undefined,
colOptions: undefined,
order: undefined,
}
break
// generate duplicate column title
const duplicateColumnTitle = getUniqueColumnName(`${column!.value.title} copy`, meta!.value!.columns!)
columnCreatePayload = {
...column!.value!,
...(column!.value.colOptions ?? {}),
title: duplicateColumnTitle,
column_name: duplicateColumnTitle.replace(/\s/g, '_'),
id: undefined,
colOptions: undefined,
order: undefined,
}
try {
@ -189,6 +163,42 @@ const duplicateColumn = async () => {
isOpen.value = false
}
const openDuplicateDlg = async () => {
if (!column?.value) return
if (column.value.uidt && [UITypes.Lookup, UITypes.Rollup].includes(column.value.uidt as UITypes)) {
duplicateVirtualColumn()
} else {
const gridViewColumnList = (await $api.dbViewColumn.list(view.value?.id as string)).list
const currentColumnIndex = gridViewColumnList.findIndex((f) => f.fk_column_id === column!.value.id)
let newColumnOrder
if (currentColumnIndex === gridViewColumnList.length - 1) {
newColumnOrder = gridViewColumnList[currentColumnIndex].order! + 1
} else {
newColumnOrder = (gridViewColumnList[currentColumnIndex].order! + gridViewColumnList[currentColumnIndex + 1].order!) / 2
}
selectedColumnExtra.value = {
pv: false,
view_id: view.value!.id as string,
column_order: {
order: newColumnOrder,
view_id: view.value!.id as string,
},
}
if (column.value.uidt === UITypes.Formula) {
nextTick(() => {
duplicateDialogRef?.value?.duplicate()
})
} else {
isDuplicateDlgOpen.value = true
}
isOpen.value = false
}
}
// add column before or after current column
const addColumn = async (before = false) => {
const gridViewColumnList = (await $api.dbViewColumn.list(view.value?.id as string)).list
@ -335,10 +345,7 @@ const onInsertAfter = () => {
<a-divider class="!my-0" />
<a-menu-item
v-if="column.uidt !== UITypes.LinkToAnotherRecord && column.uidt !== UITypes.Lookup && !column.pk"
@click="duplicateColumn"
>
<a-menu-item v-if="!column?.pk" @click="openDuplicateDlg">
<div v-e="['a:field:duplicate']" class="nc-column-duplicate nc-header-menu-item my-0.5">
<component :is="iconMap.duplicate" class="text-gray-700 mx-0.75" />
<!-- Duplicate -->
@ -372,6 +379,13 @@ const onInsertAfter = () => {
</template>
</a-dropdown>
<SmartsheetHeaderDeleteColumnModal v-model:visible="showDeleteColumnModal" />
<DlgColumnDuplicate
v-if="column"
ref="duplicateDialogRef"
v-model="isDuplicateDlgOpen"
:column="column"
:extra="selectedColumnExtra"
/>
</template>
<style scoped>

6
packages/nc-gui/components/smartsheet/header/VirtualCell.vue

@ -36,6 +36,8 @@ const editColumnDropdown = ref(false)
const isDropDownOpen = ref(false)
const isLocked = inject(IsLockedInj, ref(false))
provide(ColumnInj, column)
const { metas } = useMetas()
@ -124,12 +126,16 @@ const closeAddColumnDropdown = () => {
}
const openHeaderMenu = () => {
if (isLocked.value) return
if (!isForm.value && !isExpandedForm.value && isUIAllowed('fieldEdit') && !isMobileMode.value) {
editColumnDropdown.value = true
}
}
const openDropDown = (e: Event) => {
if (isLocked.value) return
if (isForm.value || isExpandedForm.value || (!isUIAllowed('fieldEdit') && !isMobileMode.value)) return
e.preventDefault()

4
packages/nc-gui/components/smartsheet/header/VirtualCellIcon.ts

@ -78,7 +78,9 @@ export default defineComponent({
setup(props) {
const columnMeta = toRef(props, 'columnMeta')
const column = inject(ColumnInj, columnMeta) as Ref<ColumnType & { colOptions: LookupType | RollupType }>
const injectedColumn = inject(ColumnInj, columnMeta) as Ref<ColumnType & { colOptions: LookupType | RollupType }>
const column = computed(() => columnMeta.value ?? injectedColumn.value)
let relationColumn: ColumnType

50
packages/nc-gui/components/smartsheet/toolbar/GroupByMenu.vue

@ -1,6 +1,6 @@
<script setup lang="ts">
import type { ColumnType, LinkToAnotherRecordType, LookupType } from 'nocodb-sdk'
import { RelationTypes, UITypes } from 'nocodb-sdk'
import { UITypes } from 'nocodb-sdk'
import {
ActiveViewInj,
IsLockedInj,
@ -15,20 +15,10 @@ import {
useNuxtApp,
useSmartsheetStoreOrThrow,
useViewColumnsOrThrow,
watch,
} from '#imports'
const groupingUidt = [
UITypes.SingleSelect,
UITypes.MultiSelect,
UITypes.Checkbox,
UITypes.Date,
UITypes.SingleLineText,
UITypes.Number,
UITypes.Rollup,
UITypes.Lookup,
UITypes.Links,
UITypes.Formula,
]
const excludedGroupingUidt = [UITypes.Attachment]
const meta = inject(MetaInj, ref())
const view = inject(ActiveViewInj, ref())
@ -62,16 +52,16 @@ const groupedByColumnIds = computed(() => groupBy.value.map((g) => g.fk_column_i
const { eventBus } = useSmartsheetStoreOrThrow()
const { isMobileMode } = useGlobal()
const btLookups = ref([])
const supportedLookups = ref([])
const fieldsToGroupBy = computed(() => {
const fields = meta.value?.columns || []
return fields.filter((field) => {
if (!groupingUidt.includes(field.uidt as UITypes)) return false
if (excludedGroupingUidt.includes(field.uidt as UITypes)) return false
if (field.uidt === UITypes.Lookup) {
return btLookups.value.includes(field.id)
return supportedLookups.value.includes(field.id)
}
return true
@ -161,25 +151,18 @@ watch(open, () => {
}
})
const loadBtLookups = async () => {
const loadAllowedLookups = async () => {
const filteredLookupCols = []
try {
for (const col of meta.value?.columns || []) {
if (col.uidt !== UITypes.Lookup) continue
let nextCol = col
let btLookup = true
// check all the relation of nested lookup columns is bt or not
// include the column only if all only if all relations are bt
while (btLookup && nextCol && nextCol.uidt === UITypes.Lookup) {
// check the lookup column is supported type or not
while (nextCol && nextCol.uidt === UITypes.Lookup) {
const lookupRelation = (await getMeta(nextCol.fk_model_id))?.columns?.find(
(c) => c.id === (nextCol.colOptions as LookupType).fk_relation_column_id,
)
if ((lookupRelation.colOptions as LinkToAnotherRecordType).type !== RelationTypes.BELONGS_TO) {
btLookup = false
continue
}
const relatedTableMeta = await getMeta((lookupRelation.colOptions as LinkToAnotherRecordType).fk_related_model_id)
@ -190,22 +173,25 @@ const loadBtLookups = async () => {
// if next column is same as root lookup column then break the loop
// since it's going to be a circular loop, and ignore the column
if (nextCol.id === col.id) {
btLookup = false
break
}
}
if (btLookup) filteredLookupCols.push(col.id)
if (nextCol.uidt !== UITypes.Attachment) filteredLookupCols.push(col.id)
}
btLookups.value = filteredLookupCols
supportedLookups.value = filteredLookupCols
} catch (e) {
console.error(e)
}
}
onMounted(async () => {
await loadBtLookups()
await loadAllowedLookups()
})
watch(meta, async () => {
await loadAllowedLookups()
})
</script>
@ -242,9 +228,7 @@ onMounted(async () => {
<LazySmartsheetToolbarFieldListAutoCompleteDropdown
v-model="group.fk_column_id"
class="caption nc-sort-field-select"
:columns="
fieldsToGroupBy.filter((f) => (f.id && !groupedByColumnIds.includes(f.id)) || f.id === group.fk_column_id)
"
:columns="fieldsToGroupBy"
:allow-empty="true"
@change="saveGroupBy"
@click.stop

2
packages/nc-gui/components/smartsheet/toolbar/OpenedViewAction.vue

@ -168,11 +168,11 @@ function openDeleteDialog() {
<NcDropdown
v-else
v-model:visible="isDropdownOpen"
v-e="['c:breadcrumb:view-actions']"
class="!xs:pointer-events-none nc-actions-menu-btn nc-view-context-btn"
overlay-class-name="nc-dropdown-actions-menu"
>
<div
v-e="['c:breadcrumb:view-actions']"
class="truncate nc-active-view-title !hover:(bg-gray-100 text-gray-800) ml-0.25 pl-1 pr-0.25 rounded-md py-1 cursor-pointer"
:class="{
'max-w-2/5': !isSharedBase && !isMobileMode && activeView?.is_default,

98
packages/nc-gui/components/smartsheet/toolbar/ViewActionMenu.vue

@ -18,8 +18,6 @@ const { isUIAllowed } = useRoles()
const isPublicView = inject(IsPublicInj, ref(false))
const isLocked = inject(IsLockedInj, ref(false))
const { $api, $e } = useNuxtApp()
const { t } = useI18n()
@ -58,7 +56,7 @@ const quickImportDialogs: Record<(typeof quickImportDialogTypes)[number], Ref<bo
) as Record<QuickImportDialogType, Ref<boolean>>
const onImportClick = (dialog: any) => {
if (isLocked.value) return
if (lockType.value === LockType.Locked) return
emits('closeModal')
dialog.value = true
@ -163,10 +161,17 @@ const onDelete = async () => {
</NcTooltip>
<NcDivider />
<template v-if="!view?.is_default">
<NcMenuItem @click="onRenameMenuClick">
<NcMenuItem v-if="lockType !== LockType.Locked" @click="onRenameMenuClick">
<GeneralIcon icon="edit" />
{{ $t('activity.renameView') }}
</NcMenuItem>
<NcTooltip v-else>
<template #title> {{ $t('msg.info.disabledAsViewLocked') }} </template>
<NcMenuItem class="!cursor-not-allowed !text-gray-400">
<GeneralIcon icon="edit" />
{{ $t('activity.renameView') }}
</NcMenuItem>
</NcTooltip>
<NcMenuItem @click="onDuplicate">
<GeneralIcon icon="duplicate" class="nc-view-copy-icon" />
{{ $t('labels.duplicateView') }}
@ -205,7 +210,7 @@ const onDelete = async () => {
},
]"
class="nc-base-menu-item"
:class="{ disabled: isLocked }"
:class="{ disabled: lockType === LockType.Locked }"
>
<component :is="iconMap.upload" />
{{ `${$t('general.upload')} ${type.toUpperCase()}` }}
@ -234,47 +239,62 @@ const onDelete = async () => {
<LazySmartsheetToolbarExportSubActions />
</NcSubMenu>
<NcDivider />
</template>
<NcSubMenu v-if="isUIAllowed('viewCreateOrEdit')" key="lock-type" class="scrollbar-thin-dull max-h-90vh overflow-auto !py-0">
<template #title>
<div
v-e="[
'c:navdraw:preview-as',
{
sidebar: props.inSidebar,
},
]"
class="flex flex-row items-center gap-x-3"
>
<div>
{{ $t('labels.viewMode') }}
</div>
<div class="nc-base-menu-item flex !flex-shrink group !py-1 !px-1 rounded-md bg-brand-50">
<LazySmartsheetToolbarLockType
hide-tick
:type="lockType"
class="flex nc-view-actions-lock-type !text-brand-500 !flex-shrink"
/>
<template v-if="isUIAllowed('viewCreateOrEdit')">
<NcDivider />
<NcSubMenu key="lock-type" class="scrollbar-thin-dull max-h-90vh overflow-auto !py-0">
<template #title>
<div
v-e="[
'c:navdraw:preview-as',
{
sidebar: props.inSidebar,
},
]"
class="flex flex-row items-center gap-x-3"
>
<div>
{{ $t('labels.viewMode') }}
</div>
<div class="nc-base-menu-item flex !flex-shrink group !py-1 !px-1 rounded-md bg-brand-50">
<LazySmartsheetToolbarLockType
hide-tick
:type="lockType"
class="flex nc-view-actions-lock-type !text-brand-500 !flex-shrink"
/>
</div>
<div class="flex flex-grow"></div>
</div>
<div class="flex flex-grow"></div>
</div>
</template>
</template>
<template #expandIcon></template>
<div class="flex py-3 px-4 font-bold uppercase text-xs text-gray-500">{{ $t('labels.viewMode') }}</div>
<a-menu-item class="!mx-1 !py-2 !rounded-md nc-view-action-lock-subaction">
<LazySmartsheetToolbarLockType :type="LockType.Collaborative" @click="changeLockType(LockType.Collaborative)" />
</a-menu-item>
<template #expandIcon></template>
<div class="flex py-3 px-4 font-bold uppercase text-xs text-gray-500">{{ $t('labels.viewMode') }}</div>
<a-menu-item class="!mx-1 !py-2 !rounded-md nc-view-action-lock-subaction">
<LazySmartsheetToolbarLockType :type="LockType.Collaborative" @click="changeLockType(LockType.Collaborative)" />
</a-menu-item>
<a-menu-item class="!mx-1 !py-2 !rounded-md nc-view-action-lock-subaction">
<LazySmartsheetToolbarLockType :type="LockType.Locked" @click="changeLockType(LockType.Locked)" />
</a-menu-item>
</NcSubMenu>
</template>
<a-menu-item class="!mx-1 !py-2 !rounded-md nc-view-action-lock-subaction">
<LazySmartsheetToolbarLockType :type="LockType.Locked" @click="changeLockType(LockType.Locked)" />
</a-menu-item>
</NcSubMenu>
<template v-if="!view.is_default">
<NcDivider />
<NcMenuItem class="!hover:bg-red-50 !text-red-500" @click="onDelete">
<NcTooltip v-if="lockType === LockType.Locked">
<template #title> {{ $t('msg.info.disabledAsViewLocked') }} </template>
<NcMenuItem class="!cursor-not-allowed !text-gray-400">
<GeneralIcon icon="delete" class="nc-view-delete-icon" />
{{
$t('general.deleteEntity', {
entity: $t('objects.view'),
})
}}
</NcMenuItem>
</NcTooltip>
<NcMenuItem v-else class="!hover:bg-red-50 !text-red-500" @click="onDelete">
<GeneralIcon icon="delete" class="nc-view-delete-icon" />
{{
$t('general.deleteEntity', {

14
packages/nc-gui/components/tabs/Smartsheet.vue

@ -171,21 +171,21 @@ watch([activeViewTitleOrId, activeTableId], () => {
<LazySmartsheetToolbar v-if="!isForm" />
<div class="flex flex-row w-full" style="height: calc(100% - var(--topbar-height))">
<Transition name="layout" mode="out-in">
<template v-if="meta">
<div class="flex flex-1 min-h-0 w-3/4">
<div v-if="activeView" class="h-full flex-1 min-w-0 min-h-0 bg-white">
<LazySmartsheetGrid v-if="isGrid" ref="grid" />
<div class="flex flex-1 min-h-0 w-3/4">
<div class="h-full flex-1 min-w-0 min-h-0 bg-white">
<LazySmartsheetGrid v-if="isGrid || !meta || !activeView" ref="grid" />
<LazySmartsheetGallery v-else-if="isGallery" />
<template v-if="activeView && meta">
<LazySmartsheetGallery v-if="isGallery" />
<LazySmartsheetForm v-else-if="isForm && !$route.query.reload" />
<LazySmartsheetKanban v-else-if="isKanban" />
<LazySmartsheetMap v-else-if="isMap" />
</div>
</template>
</div>
</template>
</div>
</Transition>
</div>
</div>

94
packages/nc-gui/components/template/Editor.vue

@ -34,12 +34,13 @@ import {
useI18n,
useNuxtApp,
useTabs,
validateTableName,
} from '#imports'
const { quickImportType, baseTemplate, importData, importColumns, importDataOnly, maxRowsToParse, sourceId, importWorker } =
defineProps<Props>()
const emit = defineEmits(['import'])
const emit = defineEmits(['import', 'error', 'change'])
dayjs.extend(utc)
@ -95,6 +96,8 @@ const importingTips = ref<Record<string, string>>({})
const checkAllRecord = ref<boolean[]>([])
const formError = ref()
const uiTypeOptions = ref<Option[]>(
(Object.keys(UITypes) as (keyof typeof UITypes)[])
.filter(
@ -124,11 +127,14 @@ const data = reactive<{
const validators = computed(() =>
data.tables.reduce<Record<string, [ReturnType<typeof fieldRequiredValidator>]>>((acc: Record<string, any>, table, tableIdx) => {
acc[`tables.${tableIdx}.table_name`] = [fieldRequiredValidator()]
acc[`tables.${tableIdx}.table_name`] = [validateTableName]
hasSelectColumn.value[tableIdx] = false
table.columns?.forEach((column, columnIdx) => {
acc[`tables.${tableIdx}.columns.${columnIdx}.column_name`] = [fieldRequiredValidator(), fieldLengthValidator()]
acc[`tables.${tableIdx}.columns.${columnIdx}.column_name`] = [
fieldRequiredValidator(),
fieldLengthValidator(base.value?.sources?.[0].type || ClientType.MYSQL),
]
acc[`tables.${tableIdx}.columns.${columnIdx}.uidt`] = [fieldRequiredValidator()]
if (isSelect(column)) {
hasSelectColumn.value[tableIdx] = true
@ -139,10 +145,12 @@ const validators = computed(() =>
}, {}),
)
const { validate, validateInfos } = useForm(data, validators)
const { validate, validateInfos, modelRef } = useForm(data, validators)
const isValid = ref(!importDataOnly)
const formRef = ref()
watch(
() => srcDestMapping.value,
() => {
@ -527,6 +535,15 @@ async function importTemplate() {
title: '',
columns: table.columns || [],
})
if (process.env.NC_SANITIZE_COLUMN_NAME !== 'false') {
// column_name could have been updated in tableCreate
// e.g. sanitize column name to something like field_1, field_2, and etc
createdTable.columns.forEach((column, i) => {
table.columns[i].column_name = column.column_name
})
}
table.id = createdTable.id
table.title = createdTable.title
@ -674,6 +691,39 @@ function handleUIDTChange(column, table) {
])
}
}
const setErrorState = (errorsFields: any[]) => {
const errorMap: any = {}
for (const error of errorsFields) {
errorMap[error.name] = error.errors
}
formError.value = errorMap
}
watch(formRef, () => {
setTimeout(async () => {
try {
await validate()
emit('change')
formError.value = null
} catch (e: any) {
emit('error', e)
setErrorState(e.errorFields)
}
}, 500)
})
watch(modelRef, async () => {
try {
await validate()
emit('change')
formError.value = null
} catch (e: any) {
emit('error', e)
setErrorState(e.errorFields)
}
})
</script>
<template>
@ -694,7 +744,7 @@ function handleUIDTChange(column, table) {
<a-collapse v-if="data.tables && data.tables.length" v-model:activeKey="expansionPanel" class="template-collapse" accordion>
<a-collapse-panel v-for="(table, tableIdx) of data.tables" :key="tableIdx">
<template #header>
<span class="font-weight-bold text-lg flex items-center gap-2">
<span class="font-weight-bold text-lg flex items-center gap-2 truncate">
<component :is="iconMap.table" class="text-primary" />
{{ table.table_name }}
</span>
@ -769,7 +819,7 @@ function handleUIDTChange(column, table) {
</a-card>
<a-card v-else>
<a-form :model="data" name="template-editor-form" @keydown.enter="emit('import')">
<a-form ref="formRef" :model="data" name="template-editor-form" @keydown.enter="emit('import')">
<p v-if="data.tables && quickImportType === 'excel'" class="text-center">
{{ data.tables.length }} sheet{{ data.tables.length > 1 ? 's' : '' }}
available for import
@ -783,22 +833,24 @@ function handleUIDTChange(column, table) {
>
<a-collapse-panel v-for="(table, tableIdx) of data.tables" :key="tableIdx">
<template #header>
<a-form-item v-if="editableTn[tableIdx]" v-bind="validateInfos[`tables.${tableIdx}.table_name`]" no-style>
<a-input
v-model:value.lazy="table.table_name"
class="max-w-xs font-weight-bold text-lg"
size="large"
hide-details
:bordered="false"
@click.stop
@blur="handleEditableTnChange(tableIdx)"
@keydown.enter="handleEditableTnChange(tableIdx)"
/>
<a-form-item v-bind="validateInfos[`tables.${tableIdx}.table_name`]" no-style>
<div class="flex flex-col w-full">
<a-input
v-model:value="table.table_name"
class="font-weight-bold text-lg"
size="large"
hide-details
:bordered="false"
@click.stop
@blur="handleEditableTnChange(tableIdx)"
@keydown.enter="handleEditableTnChange(tableIdx)"
@dblclick="setEditableTn(tableIdx, true)"
/>
<div v-if="formError?.[`tables.${tableIdx}.table_name`]" class="text-red-500 ml-3">
{{ formError?.[`tables.${tableIdx}.table_name`].join('\n') }}
</div>
</div>
</a-form-item>
<span v-else class="font-weight-bold text-lg flex items-center gap-2" @click="setEditableTn(tableIdx, true)">
<component :is="iconMap.table" class="text-primary" />
{{ table.table_name }}
</span>
</template>
<template #extra>

5
packages/nc-gui/components/virtual-cell/BelongsTo.vue

@ -6,7 +6,6 @@ import {
CellValueInj,
ColumnInj,
IsFormInj,
IsLockedInj,
IsUnderLookupInj,
ReadonlyInj,
ReloadRowDataHookInj,
@ -35,8 +34,6 @@ const readOnly = inject(ReadonlyInj, ref(false))
const isForm = inject(IsFormInj, ref(false))
const isLocked = inject(IsLockedInj, ref(false))
const isUnderLookup = inject(IsUnderLookupInj, ref(false))
const { isUIAllowed } = useRoles()
@ -103,7 +100,7 @@ const belongsToColumn = computed(
</div>
<div
v-if="!readOnly && !isLocked && (isUIAllowed('dataEdit') || isForm) && !isUnderLookup"
v-if="!readOnly && (isUIAllowed('dataEdit') || isForm) && !isUnderLookup"
class="flex justify-end gap-1 min-h-[30px] items-center"
>
<GeneralIcon

5
packages/nc-gui/components/virtual-cell/HasMany.vue

@ -5,7 +5,6 @@ import {
CellValueInj,
ColumnInj,
IsFormInj,
IsLockedInj,
IsUnderLookupInj,
ReadonlyInj,
ReloadRowDataHookInj,
@ -31,8 +30,6 @@ const isForm = inject(IsFormInj)
const readOnly = inject(ReadonlyInj, ref(false))
const isLocked = inject(IsLockedInj)
const isUnderLookup = inject(IsUnderLookupInj, ref(false))
const listItemsDlg = ref(false)
@ -121,7 +118,7 @@ useSelectedCellKeyupListener(inject(ActiveCellInj, ref(false)), (e: KeyboardEven
</template>
</div>
<div v-if="!isLocked && !isUnderLookup" class="flex justify-end gap-1 min-h-[30px] items-center">
<div v-if="!isUnderLookup" class="flex justify-end gap-1 min-h-[30px] items-center">
<GeneralIcon
icon="expand"
class="select-none transform text-sm nc-action-icon text-gray-500/50 hover:text-gray-500 nc-arrow-expand"

13
packages/nc-gui/components/virtual-cell/Links.vue

@ -17,8 +17,6 @@ const isForm = inject(IsFormInj)
const readOnly = inject(ReadonlyInj, ref(false))
const isLocked = inject(IsLockedInj, ref(false))
const isUnderLookup = inject(IsUnderLookupInj, ref(false))
const colTitle = computed(() => column.value?.title || '')
@ -79,15 +77,13 @@ const onAttachRecord = () => {
const openChildList = () => {
if (isUnderLookup.value) return
if (!isLocked.value) {
childListDlg.value = true
}
childListDlg.value = true
}
useSelectedCellKeyupListener(inject(ActiveCellInj, ref(false)), (e: KeyboardEvent) => {
switch (e.key) {
case 'Enter':
if (isLocked.value || listItemsDlg.value) return
if (listItemsDlg.value) return
childListDlg.value = true
e.stopPropagation()
break
@ -112,7 +108,7 @@ const openListDlg = () => {
<div class="flex w-full group items-center nc-links-wrapper" @dblclick.stop="openChildList">
<div class="block flex-shrink truncate">
<component
:is="isLocked || isUnderLookup ? 'span' : 'a'"
:is="isUnderLookup ? 'span' : 'a'"
v-e="['c:cell:links:modal:open']"
:title="textVal"
class="text-center nc-datatype-link underline-transparent"
@ -124,14 +120,13 @@ const openListDlg = () => {
</div>
<div class="flex-grow" />
<div v-if="!isLocked && !isUnderLookup" class="!xs:hidden flex justify-end hidden group-hover:flex items-center">
<div v-if="!isUnderLookup" class="!xs:hidden flex justify-end hidden group-hover:flex items-center">
<MdiPlus
v-if="(!readOnly && isUIAllowed('dataEdit')) || isForm"
class="select-none !text-md text-gray-700 nc-action-icon nc-plus"
@click.stop="openListDlg"
/>
</div>
<LazyVirtualCellComponentsListItems
v-if="listItemsDlg || childListDlg"
v-model="listItemsDlg"

14
packages/nc-gui/components/virtual-cell/Lookup.vue

@ -98,7 +98,7 @@ const { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning, activ
<template>
<div
class="h-full w-full"
class="h-full w-full nc-lookup-cell"
:style="{ height: rowHeight && rowHeight !== 1 ? `${rowHeight * 2}rem` : `2.85rem` }"
@dblclick="activateShowEditNonEditableFieldWarning"
>
@ -110,9 +110,13 @@ const { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning, activ
>
<template v-if="lookupColumn">
<!-- Render virtual cell -->
<div v-if="isVirtualCol(lookupColumn)">
<div v-if="isVirtualCol(lookupColumn)" class="flex">
<!-- If non-belongs-to LTAR column then pass the array value, else iterate and render -->
<template
v-if="lookupColumn.uidt === UITypes.LinkToAnotherRecord && lookupColumn.colOptions.type === RelationTypes.BELONGS_TO"
v-if="
lookupColumn.uidt !== UITypes.LinkToAnotherRecord ||
(lookupColumn.uidt === UITypes.LinkToAnotherRecord && lookupColumn.colOptions.type === RelationTypes.BELONGS_TO)
"
>
<LazySmartsheetVirtualCell
v-for="(v, i) of arrValue"
@ -206,4 +210,8 @@ const { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning, activ
@apply bg-gray-200;
}
}
.nc-lookup-cell .nc-text-area-clamped-text {
@apply !mr-1;
}
</style>

5
packages/nc-gui/components/virtual-cell/ManyToMany.vue

@ -6,7 +6,6 @@ import {
CellValueInj,
ColumnInj,
IsFormInj,
IsLockedInj,
IsUnderLookupInj,
ReadonlyInj,
ReloadRowDataHookInj,
@ -33,8 +32,6 @@ const isForm = inject(IsFormInj)
const readOnly = inject(ReadonlyInj, ref(false))
const isLocked = inject(IsLockedInj)
const isUnderLookup = inject(IsUnderLookupInj, ref(false))
const listItemsDlg = ref(false)
@ -123,7 +120,7 @@ const m2mColumn = computed(
</template>
</div>
<div v-if="(!isLocked && !isUnderLookup) || isForm" class="flex justify-end gap-1 min-h-[30px] items-center">
<div v-if="!isUnderLookup || isForm" class="flex justify-end gap-1 min-h-[30px] items-center">
<GeneralIcon
icon="expand"
class="text-sm nc-action-icon text-gray-500/50 hover:text-gray-500 nc-arrow-expand"

3
packages/nc-gui/components/virtual-cell/QrCode.vue

@ -92,9 +92,10 @@ const { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning } = us
:style="{ height: rowHeight ? `${rowHeight * 1.4}rem` : `1.4rem` }"
:src="qrCode"
:alt="$t('title.qrCode')"
class="min-w-[1.4em]"
@click="showQrModal"
/>
<img v-else-if="showQrCode" class="mx-auto" :src="qrCode" :alt="$t('title.qrCode')" @click="showQrModal" />
<img v-else-if="showQrCode" class="mx-auto min-w-[1.4em]" :src="qrCode" :alt="$t('title.qrCode')" @click="showQrModal" />
</div>
<div v-if="showEditNonEditableFieldWarning" class="text-left text-wrap mt-2 text-[#e65100] text-xs">
{{ $t('msg.warning.nonEditableFields.computedFieldUnableToClear') }}

8
packages/nc-gui/components/virtual-cell/components/Header.vue

@ -5,9 +5,9 @@ import FileIcon from '~icons/nc-icons/file'
import { iconMap } from '#imports'
const { relation, relatedTableTitle, displayValue, showHeader, tableTitle } = defineProps<{
const { relation, relatedTableTitle, displayValue, header, tableTitle } = defineProps<{
relation: string
showHeader?: boolean
header?: string | null
tableTitle: string
relatedTableTitle: string
displayValue?: string
@ -54,12 +54,12 @@ const relationMeta = computed(() => {
<template>
<div class="flex sm:justify-between relative pb-2 items-center">
<div v-if="!isMobileMode" class="flex text-base font-bold justify-start items-center min-w-36">
{{ showHeader ? 'Linked Records' : '' }}
{{ header ?? '' }}
</div>
<div class="flex flex-row sm:w-[calc(100%-16rem)] xs:w-full items-center justify-center gap-2 xs:(h-full)">
<div class="flex sm:justify-end w-[calc(50%-1.5rem)] xs:(w-[calc(50%-1.5rem)] h-full)">
<div
class="flex max-w-full xs:w-full flex-shrink-0 xs:(h-full) rounded-md gap-1 text-brand-500 items-center bg-gray-100 px-2 py-1"
class="flex max-w-full xs:w-full flex-shrink-0 xs:(h-full) rounded-md gap-1 text-gray-700 items-center bg-gray-100 px-2 py-1"
>
<FileIcon class="w-4 h-4 min-w-4" />
<span class="truncate">

11
packages/nc-gui/components/virtual-cell/components/ItemChip.vue

@ -4,7 +4,6 @@ import { UITypes, isVirtualCol } from 'nocodb-sdk'
import {
ActiveCellInj,
IsFormInj,
IsLockedInj,
ReadonlyInj,
iconMap,
inject,
@ -37,13 +36,11 @@ const active = inject(ActiveCellInj, ref(false))
const isForm = inject(IsFormInj)!
const isLocked = inject(IsLockedInj, ref(false))
const { open } = useExpandedFormDetached()
function openExpandedForm() {
const rowId = extractPkFromRow(item, relatedTableMeta.value.columns as ColumnType[])
if (!readOnly.value && !isLocked.value && !readonlyProp && rowId) {
if (!readOnly.value && !readonlyProp && rowId) {
open({
isOpen: true,
row: { row: item, rowMeta: {}, oldRow: { ...item } },
@ -98,11 +95,7 @@ export default {
</template>
</span>
<div
v-show="active || isForm"
v-if="showUnlinkButton && !readOnly && !isLocked && isUIAllowed('dataEdit')"
class="flex items-center"
>
<div v-show="active || isForm" v-if="showUnlinkButton && !readOnly && isUIAllowed('dataEdit')" class="flex items-center">
<component
:is="iconMap.closeThick"
class="nc-icon unlink-icon text-xs text-gray-500/50 group-hover:text-gray-500"

9
packages/nc-gui/components/virtual-cell/components/ListChildItems.vue

@ -134,10 +134,10 @@ onKeyStroke('Escape', () => {
})
/*
to render same number of skelton as the number of cards
to render same number of skeleton as the number of cards
displayed
*/
const skeltonCount = computed(() => {
const skeletonCount = computed(() => {
if (props.items < 10 && childrenListPagination.page === 1) {
return props.items
}
@ -166,6 +166,7 @@ const isDataExist = computed<boolean>(() => {
const linkOrUnLink = (rowRef: Record<string, string>, id: string) => {
if (isSharedBase.value) return
if (readonly.value) return
if (isPublic.value && !isForm.value) return
if (isNew.value || isChildrenListLinked.value[parseInt(id)]) {
@ -192,7 +193,7 @@ const linkOrUnLink = (rowRef: Record<string, string>, id: string) => {
:relation="relation"
:linked-records="childrenListCount"
:table-title="meta?.title"
:show-header="true"
:header="$t('activity.linkedRecords')"
:related-table-title="relatedTableMeta?.title"
:display-value="row.row[displayValueProp]"
/>
@ -222,7 +223,7 @@ const linkOrUnLink = (rowRef: Record<string, string>, id: string) => {
<div class="cursor-pointer pr-1">
<template v-if="isChildrenLoading">
<div
v-for="(x, i) in Array.from({ length: skeltonCount })"
v-for="(x, i) in Array.from({ length: skeletonCount })"
:key="i"
class="!border-2 flex flex-row gap-2 mb-2 transition-all !rounded-xl relative !border-gray-200 hover:bg-gray-50"
>

5
packages/nc-gui/components/virtual-cell/components/ListItem.vue

@ -77,6 +77,7 @@ const attachments: ComputedRef<Attachment[]> = computed(() => {
'!bg-white': isLoading,
'!border-1': isLinked && !isLoading,
'!hover:border-gray-400': !isLinked,
'!cursor-auto !hover:bg-white': readonly,
}"
:body-style="{ padding: 0 }"
:hoverable="false"
@ -109,7 +110,7 @@ const attachments: ComputedRef<Attachment[]> = computed(() => {
v-if="isLinked && !isLoading"
class="text-brand-500 text-0.875"
:class="{
'!group-hover:mr-12': fields.length === 0,
'!group-hover:mr-12': fields.length === 0 && !readonly,
}"
>
<LinkIcon class="w-4 h-4" />
@ -118,7 +119,7 @@ const attachments: ComputedRef<Attachment[]> = computed(() => {
<MdiLoading
v-else-if="isLoading"
:class="{
'!group-hover:mr-8': fields.length === 0,
'!group-hover:mr-8': fields.length === 0 && !readonly,
}"
class="w-6 h-6 !text-brand-500 animate-spin"
/>

69
packages/nc-gui/components/virtual-cell/components/ListItems.vue

@ -1,5 +1,5 @@
<script lang="ts" setup>
import { RelationTypes, UITypes, isLinksOrLTAR, isSystemColumn } from 'nocodb-sdk'
import { RelationTypes, isLinksOrLTAR, isSystemColumn } from 'nocodb-sdk'
import type { ColumnType, LinkToAnotherRecordType } from 'nocodb-sdk'
import InboxIcon from '~icons/nc-icons/inbox'
import {
@ -29,6 +29,8 @@ const { isSharedBase } = storeToRefs(useBase())
const filterQueryRef = ref()
const { t } = useI18n()
const { $e } = useNuxtApp()
const {
@ -53,6 +55,8 @@ const { addLTARRef, isNew, removeLTARRef, state: rowState } = useSmartsheetRowSt
const isPublic = inject(IsPublicInj, ref(false))
const isExpandedFormCloseAfterSave = ref(false)
isChildrenExcludedLoading.value = true
const isForm = inject(IsFormInj, ref(false))
@ -112,7 +116,8 @@ const newRowState = computed(() => {
if (isNew.value) return {}
const colOpt = (injectedColumn?.value as ColumnType)?.colOptions as LinkToAnotherRecordType
const colInRelatedTable: ColumnType | undefined = relatedTableMeta?.value?.columns?.find((col) => {
if (col.uidt !== UITypes.LinkToAnotherRecord) return false
// Links as for the case of 'mm' we need the 'Links' column
if (!isLinksOrLTAR(col)) return false
const colOpt1 = col?.colOptions as LinkToAnotherRecordType
if (colOpt1?.fk_related_model_id !== meta.value.id) return false
@ -157,6 +162,10 @@ const relation = computed(() => {
watch(expandedFormDlg, () => {
if (!expandedFormDlg.value) {
isExpandedFormCloseAfterSave.value = false
if (!isForm.value) {
loadChildrenList()
}
loadChildrenExcludedList(rowState.value)
}
})
@ -173,6 +182,42 @@ const onClick = (refRow: any, id: string) => {
linkRow(refRow, Number.parseInt(id))
}
}
const addNewRecord = () => {
expandedFormRow.value = {}
expandedFormDlg.value = true
isExpandedFormCloseAfterSave.value = true
}
const onCreatedRecord = (record: any) => {
const msgVNode = h(
'div',
{
class: 'ml-1 inline-flex flex-col gap-1 items-start',
},
[
h(
'span',
{
class: 'font-semibold',
},
t('activity.recordCreatedLinked'),
),
h(
'span',
{
class: 'text-gray-500',
},
t('activity.gotSavedLinkedSuccessfully', {
tableName: relatedTableMeta.value?.title,
recordTitle: record[relatedTableDisplayValueProp.value],
}),
),
],
)
message.success(msgVNode)
}
</script>
<template>
@ -191,14 +236,14 @@ const onClick = (refRow: any, id: string) => {
:table-title="meta?.title"
:related-table-title="relatedTableMeta?.title"
:display-value="row.row[displayValueProp]"
:header="$t('activity.addNewLink')"
/>
<div class="!xs:hidden my-3 bg-gray-50 border-gray-50 border-b-2"></div>
<div class="flex mt-2 mb-2 items-center gap-2">
<div
class="flex items-center border-1 p-1 rounded-md w-full border-gray-200"
:class="{ '!border-primary': childrenExcludedListPagination.query.length !== 0 || isFocused }"
>
<MdiMagnify class="w-5 h-5 ml-2" />
<MdiMagnify class="w-5 h-5 ml-2 text-gray-500" />
<a-input
ref="filterQueryRef"
v-model:value="childrenExcludedListPagination.query"
@ -223,12 +268,7 @@ const onClick = (refRow: any, id: string) => {
type="secondary"
:size="isMobileMode ? 'medium' : 'small'"
class="!text-brand-500"
@click="
() => {
expandedFormRow = {}
expandedFormDlg = true
}
"
@click="addNewRecord"
>
<div class="flex items-center gap-1 px-4"><MdiPlus v-if="!isMobileMode" /> {{ $t('activity.newRecord') }}</div>
</NcButton>
@ -344,6 +384,15 @@ const onClick = (refRow: any, id: string) => {
:row-id="extractPkFromRow(expandedFormRow, relatedTableMeta.columns as ColumnType[])"
:state="newRowState"
use-meta-fields
:close-after-save="isExpandedFormCloseAfterSave"
:new-record-header="
isExpandedFormCloseAfterSave
? $t('activity.tableNameCreateNewRecord', {
tableName: relatedTableMeta?.title,
})
: undefined
"
@created-record="onCreatedRecord"
/>
</Suspense>
</NcModal>

10
packages/nc-gui/composables/useColumnCreateStore.ts

@ -40,6 +40,8 @@ const [useProvideColumnCreateStore, useColumnCreateStore] = createInjectionState
const { sqlUis } = storeToRefs(baseStore)
const { bases } = storeToRefs(useBases())
const { $api } = useNuxtApp()
const { getMeta } = useMetas()
@ -64,6 +66,12 @@ const [useProvideColumnCreateStore, useColumnCreateStore] = createInjectionState
isXcdbBaseFunc(meta.value?.source_id ? meta.value?.source_id : Object.keys(sqlUis.value)[0]),
)
const source = computed(() =>
meta.value && meta.value.source_id && meta.value.base_id
? bases.value.get(meta.value?.base_id as string)?.sources?.find((s) => s.id === meta.value!.source_id)
: undefined,
)
const idType = null
const additionalValidations = ref<ValidationsObj>({})
@ -128,7 +136,7 @@ const [useProvideColumnCreateStore, useColumnCreateStore] = createInjectionState
})
},
},
fieldLengthValidator(),
fieldLengthValidator(source.value?.type || ClientType.MYSQL),
],
uidt: [
{

4
packages/nc-gui/composables/useData.ts

@ -34,10 +34,6 @@ export function useData(args: {
}) {
const { meta, viewMeta, formattedData, paginationData, callbacks } = args
if (!meta) {
throw new Error('Table meta is not available')
}
const { t } = useI18n()
const { getMeta, metas } = useMetas()

1
packages/nc-gui/composables/useGlobal/state.ts

@ -109,6 +109,7 @@ export function useGlobalState(storageKey = 'nocodb-gui-v2'): State {
automationLogLevel: 'OFF',
disableEmailAuth: false,
dashboardPath: '/dashboard',
inviteOnlySignup: false,
})
/** reactive token payload */

1
packages/nc-gui/composables/useGlobal/types.ts

@ -34,6 +34,7 @@ export interface AppInfo {
disableEmailAuth: boolean
mainSubDomain?: string
dashboardPath: string
inviteOnlySignup: boolean
}
export interface StoredState {

4
packages/nc-gui/composables/useMultiSelect/index.ts

@ -486,6 +486,10 @@ export function useMultiSelect(
return true
}
if (isExpandedCellInputExist()) {
return
}
if (!isCellActive.value || activeCell.row === null || activeCell.col === null) {
return
}

58
packages/nc-gui/composables/useTableNew.ts

@ -1,5 +1,7 @@
import type { ColumnType, LinkToAnotherRecordType, TableType } from 'nocodb-sdk'
import { UITypes, isSystemColumn } from 'nocodb-sdk'
import type { SidebarTableNode } from '~/lib'
import {
Modal,
SYSTEM_COLUMNS,
@ -58,7 +60,7 @@ export function useTableNew(param: { onTableCreate?: (tableMeta: TableType) => v
const tables = computed(() => baseTables.value.get(param.baseId) || [])
const base = computed(() => bases.value.get(param.baseId))
const openTable = async (table: TableType) => {
const openTable = async (table: SidebarTableNode) => {
if (!table.base_id) return
let base = bases.value.get(table.base_id)
@ -82,21 +84,49 @@ export function useTableNew(param: { onTableCreate?: (tableMeta: TableType) => v
baseIdOrBaseId = route.value.params.baseId as string
}
await getMeta(table.id as string, (route.value.params?.viewId as string) !== table.id)
const navigateToTable = async () => {
if (openedViewsTab.value === 'view') {
await navigateTo({
path: `/${workspaceIdOrType}/${baseIdOrBaseId}/${table?.id}`,
query: route.value.query,
})
}
await loadViews({ tableId: table.id as string })
table.isViewsLoading = true
const views = viewsByTable.value.get(table.id as string) ?? []
if (openedViewsTab.value !== 'view' && views.length && views[0].id) {
await navigateTo({
path: `/${workspaceIdOrType}/${baseIdOrBaseId}/${table?.id}/${views[0].id}/${openedViewsTab.value}`,
query: route.value.query,
})
} else
await navigateTo({
path: `/${workspaceIdOrType}/${baseIdOrBaseId}/${table?.id}`,
query: route.value.query,
})
try {
await loadViews({ tableId: table.id as string })
const views = viewsByTable.value.get(table.id as string) ?? []
if (openedViewsTab.value !== 'view' && views.length && views[0].id) {
// find the default view and navigate to it, if not found navigate to the first one
const defaultView = views.find((v) => v.is_default) || views[0]
await navigateTo({
path: `/${workspaceIdOrType}/${baseIdOrBaseId}/${table?.id}/${defaultView.id}/${openedViewsTab.value}`,
query: route.value.query,
})
}
} catch (e) {
console.error(e)
} finally {
table.isViewsLoading = false
}
}
const loadTableMeta = async () => {
table.isMetaLoading = true
try {
await getMeta(table.id as string)
} catch (e) {
console.error(e)
} finally {
table.isMetaLoading = false
}
}
await Promise.all([navigateToTable(), loadTableMeta()])
}
const createTable = async () => {

6
packages/nc-gui/composables/useViewData.ts

@ -42,10 +42,6 @@ export function useViewData(
const meta = computed(() => _meta.value || activeTable.value)
const metaId = computed(() => _meta.value?.id || activeTableId.value)
if (!meta.value) {
throw new Error('Table meta is not available')
}
const { t } = useI18n()
const optimisedQuery = useState('optimisedQuery', () => true)
@ -190,6 +186,8 @@ export function useViewData(
controller.value = CancelToken.source()
isPaginationLoading.value = true
const response = !isPublic.value
? await api.dbViewRow.list(
'noco',

10
packages/nc-gui/composables/useViewGroupBy.ts

@ -89,6 +89,12 @@ export const useViewGroupBy = (view: Ref<ViewType | undefined>, where?: Computed
if (col.uidt === UITypes.Checkbox) {
return value ? GROUP_BY_VARS.TRUE : GROUP_BY_VARS.FALSE
}
// convert to JSON string if non-string value
if (value && typeof value === 'object') {
value = JSON.stringify(value)
}
return value ?? GROUP_BY_VARS.NULL
}
@ -144,13 +150,13 @@ export const useViewGroupBy = (view: Ref<ViewType | undefined>, where?: Computed
const calculateNestedWhere = (nestedIn: GroupNestedIn[], existing = '') => {
return nestedIn.reduce((acc, curr) => {
if (curr.key === GROUP_BY_VARS.NULL) {
acc += `${acc.length ? '~and' : ''}(${curr.title},blank)`
acc += `${acc.length ? '~and' : ''}(${curr.title},gb_null)`
} else if (curr.column_uidt === UITypes.Checkbox) {
acc += `${acc.length ? '~and' : ''}(${curr.title},${curr.key === GROUP_BY_VARS.TRUE ? 'checked' : 'notchecked'})`
} else if ([UITypes.Date, UITypes.DateTime].includes(curr.column_uidt as UITypes)) {
acc += `${acc.length ? '~and' : ''}(${curr.title},eq,exactDate,${curr.key})`
} else {
acc += `${acc.length ? '~and' : ''}(${curr.title},eq,${curr.key})`
acc += `${acc.length ? '~and' : ''}(${curr.title},gb_eq,${curr.key})`
}
return acc
}, existing)

131
packages/nc-gui/helpers/dbTiptapExtensions/links.ts

@ -0,0 +1,131 @@
import TiptapLink from '@tiptap/extension-link'
import { mergeAttributes } from '@tiptap/core'
import { Plugin, TextSelection } from 'prosemirror-state'
import type { AddMarkStep, Step } from 'prosemirror-transform'
export const Link = TiptapLink.extend({
addOptions() {
return {
openOnClick: true,
linkOnPaste: true,
autolink: true,
protocols: [],
HTMLAttributes: {
target: '_blank',
rel: 'noopener noreferrer nofollow',
class: null,
},
validate: undefined,
internal: false,
}
},
addAttributes() {
return {
href: {
default: null,
},
target: {
default: this.options.HTMLAttributes.target,
},
class: {
default: this.options.HTMLAttributes.class,
},
}
},
renderHTML({ HTMLAttributes }) {
const attr = mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)
return ['a', attr, 0]
},
addKeyboardShortcuts() {
return {
'Mod-j': () => {
const selection = this.editor.view.state.selection
this.editor
.chain()
.toggleLink({
href: '',
})
.setTextSelection(selection.to)
.run()
setTimeout(() => {
const linkInput = document.querySelector('.nc-text-area-rich-link-option-input')
if (linkInput) {
;(linkInput as any).focus()
}
}, 100)
},
'Space': () => {
// If we press space twice we stop the link mark and have normal text
const editor = this.editor
const selection = editor.view.state.selection
const nodeBefore = selection.$to.nodeBefore
const nodeAfter = selection.$to.nodeAfter
if (!nodeBefore) return false
const nodeBeforeText = nodeBefore.text!
// If we are not inside a link, we don't do anything
if (
!nodeBefore?.marks.some((mark) => mark.type.name === 'link') ||
nodeAfter?.marks.some((mark) => mark.type.name === 'link')
) {
return false
}
// Last text character should be a space
if (nodeBeforeText[nodeBeforeText.length - 1] !== ' ') {
return false
}
editor.view.dispatch(
editor.view.state.tr.removeMark(selection.$to.pos - 1, selection.$to.pos, editor.view.state.schema.marks.link),
)
return true
},
} as any
},
addProseMirrorPlugins() {
return [
// To have proseMirror plugins from the parent extension
...(this.parent?.() ?? []),
new Plugin({
//
// Put cursor at the end of the link when we add a link
//
appendTransaction: (transactions, _, newState) => {
try {
if (transactions.length !== 1) return null
const steps = transactions[0].steps
if (steps.length !== 1) return null
const step: Step = steps[0] as Step
const stepJson = step.toJSON()
// Ignore we are not adding a mark(i.e link, bold, etc)
if (stepJson.stepType !== 'addMark') return null
const addMarkStep: AddMarkStep = step as AddMarkStep
if (!addMarkStep) return null
if (addMarkStep.from === addMarkStep.to) return null
if (addMarkStep.mark.type.name !== 'link') return null
const { tr } = newState
return tr.setSelection(new TextSelection(tr.doc.resolve(addMarkStep.to)))
} catch (e) {
console.error(e)
return null
}
},
}),
]
},
}).configure({
openOnClick: false,
})

186
packages/nc-gui/helpers/dbTiptapExtensions/task-item.ts

@ -0,0 +1,186 @@
import type { KeyboardShortcutCommand } from '@tiptap/core'
import { Node, mergeAttributes, wrappingInputRule } from '@tiptap/core'
import type { Node as ProseMirrorNode } from '@tiptap/pm/model'
export interface TaskItemOptions {
onReadOnlyChecked?: (node: ProseMirrorNode, checked: boolean) => boolean
nested: boolean
HTMLAttributes: Record<string, any>
taskListTypeName: string
}
export const inputRegex = /^\s*\[( |x)?\]\s$/i
export const TaskItem = Node.create<TaskItemOptions>({
name: 'taskItem',
addOptions() {
return {
nested: false,
HTMLAttributes: {},
taskListTypeName: 'taskList',
}
},
content() {
return this.options.nested ? 'paragraph block*' : 'paragraph+'
},
defining: true,
addAttributes() {
return {
checked: {
default: false,
keepOnSplit: false,
parseHTML: (element) => element.getAttribute('data-checked') === 'true',
renderHTML: (attributes) => ({
'data-checked': attributes.checked,
}),
},
}
},
parseHTML() {
return [
{
tag: `li[data-type="${this.name}"]`,
priority: 51,
},
]
},
renderHTML({ node, HTMLAttributes }) {
return [
'li',
mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {
'data-type': this.name,
}),
[
'label',
[
'input',
{
type: 'checkbox',
checked: node.attrs.checked ? 'checked' : null,
},
],
['span'],
],
['div', 0],
]
},
addKeyboardShortcuts() {
const shortcuts: {
[key: string]: KeyboardShortcutCommand
} = {
'Enter': () => this.editor.commands.splitListItem(this.name),
'Shift-Tab': () => this.editor.commands.liftListItem(this.name),
}
if (!this.options.nested) {
return shortcuts
}
return {
...shortcuts,
Tab: () => this.editor.commands.sinkListItem(this.name),
}
},
addNodeView() {
return ({ node, HTMLAttributes, getPos, editor }) => {
const listItem = document.createElement('li')
const checkboxWrapper = document.createElement('label')
const checkboxStyler = document.createElement('span')
const checkbox = document.createElement('input')
const content = document.createElement('div')
checkboxWrapper.contentEditable = 'false'
checkbox.type = 'checkbox'
checkbox.addEventListener('change', (event) => {
// if the editor isn’t editable and we don't have a handler for
// readonly checks we have to undo the latest change
if (!editor.isEditable && !this.options.onReadOnlyChecked) {
checkbox.checked = !checkbox.checked
return
}
const { checked } = event.target as any
if (editor.isEditable && typeof getPos === 'function') {
editor
.chain()
.focus(undefined, { scrollIntoView: false })
.command(({ tr }) => {
const position = getPos()
const currentNode = tr.doc.nodeAt(position)
tr.setNodeMarkup(position, undefined, {
...currentNode?.attrs,
checked,
})
return true
})
.run()
}
if (!editor.isEditable && this.options.onReadOnlyChecked) {
// Reset state if onReadOnlyChecked returns false
if (!this.options.onReadOnlyChecked(node, checked)) {
checkbox.checked = !checkbox.checked
}
}
})
Object.entries(this.options.HTMLAttributes).forEach(([key, value]) => {
listItem.setAttribute(key, value)
})
listItem.dataset.checked = node.attrs.checked
if (node.attrs.checked) {
checkbox.setAttribute('checked', 'checked')
}
checkboxWrapper.append(checkbox, checkboxStyler)
listItem.append(checkboxWrapper, content)
Object.entries(HTMLAttributes).forEach(([key, value]) => {
listItem.setAttribute(key, value)
})
return {
dom: listItem,
contentDOM: content,
update: (updatedNode) => {
if (updatedNode.type !== this.type) {
return false
}
listItem.dataset.checked = updatedNode.attrs.checked
if (updatedNode.attrs.checked) {
checkbox.setAttribute('checked', 'checked')
} else {
checkbox.removeAttribute('checked')
}
return true
},
}
}
},
addInputRules() {
return [
wrappingInputRule({
find: inputRegex,
type: this.type,
getAttributes: (match) => ({
checked: match[match.length - 1].toLowerCase() === 'x',
}),
}),
]
},
})

580
packages/nc-gui/lang/ar.json

@ -1,5 +1,45 @@
{
"dashboards": {
"create_new_dashboard_project": "Create New Interface",
"connect_data_sources": "Connect data sources",
"alert": "Alert",
"alert-message": "No databases have been connected. Connect database bases to build interfaces. Skip this step and add databases from the base home page later.",
"select_database_projects_that_you_want_to_link_to_this_dashboard_projects": "Select Database Bases that you want to link to this Interface.",
"create_interface": "Create interface",
"project_name": "Base Name",
"connect": "Connect",
"buttonActionTypes": {
"open_external_url": "Open external link",
"delete_record": "Delete record",
"update_record": "Update record",
"open_layout": "Open layout"
},
"widgets": {
"static_text": "Text",
"chart": "Chart",
"table": "Table",
"image": "Image",
"map": "Map",
"button": "Button",
"number": "Number",
"bar_chart": "Bar Chart",
"line_chart": "Line Chart",
"area_chart": "Area Chart",
"pie_chart": "Pie Chart",
"donut_chart": "Donut Chart",
"scatter_plot": "Scatter Plot",
"bubble_chart": "Bubble Chart",
"radar_chart": "Radar Chart",
"polar_area_chart": "Polar Area Chart",
"radial_bar_chart": "Radial Bar Chart",
"heatmap_chart": "Heatmap Chart",
"treemap_chart": "Treemap Chart",
"box_plot_chart": "Box Plot Chart",
"candlestick_chart": "Candlestick Chart"
}
},
"general": {
"quit": "Quit",
"home": "الرئيسية",
"load": "تحميل",
"open": "فتح",
@ -7,27 +47,67 @@
"yes": "نعم",
"no": "لا",
"ok": "حسنا",
"back": "Back",
"and": "و",
"or": "أو",
"add": "أضف",
"edit": "تحرير",
"link": "Link",
"links": "Links",
"remove": "إزالة",
"import": "Import",
"logout": "Log Out",
"empty": "Empty",
"changeIcon": "Change Icon",
"save": "حفظ",
"available": "Available",
"abort": "Abort",
"saving": "Saving",
"cancel": "إلغاء",
"null": "Null",
"escape": "Escape",
"hex": "Hex",
"clear": "Clear",
"slack": "Slack",
"comment": "Comment",
"microsoftTeams": "Microsoft Teams",
"discord": "Discord",
"matterMost": "Mattermost",
"twilio": "Twilio",
"whatsappTwilio": "WhatsApp Twilio",
"quote": "Quote",
"submit": "إرسال",
"create": "إنشاء",
"createEntity": "Create {entity}",
"creating": "Creating",
"creatingEntity": "Creating {entity}",
"details": "Details",
"skip": "Skip",
"code": "Code",
"duplicate": "Duplicate",
"duplicating": "Duplicating",
"activate": "Activate",
"action": "Action",
"insert": "إدراج",
"delete": "حذف",
"deleteEntity": "Delete {entity}",
"bulkInsert": "Bulk Insert",
"bulkDelete": "Bulk Delete",
"bulkUpdate": "Bulk Update",
"deleting": "Deleting",
"update": "تحديث",
"rename": "إعادة تسمية",
"reload": "تحديث",
"reset": "إعادة تعيين",
"install": "تثبيت",
"show": "عرض",
"access": "Access",
"visibility": "Visibility",
"hide": "إخفاء",
"deprecated": "Deprecated",
"showAll": "عرض الكل",
"hideAll": "إخفاء الكل",
"notFound": "Not found",
"showMore": "عرض المزيد",
"showOptions": "إظهار الخيارات",
"hideOptions": "إخفاء الخيارات",
@ -47,6 +127,8 @@
"upload": "رفع",
"download": "تحميل",
"default": "افتراضي",
"base": "Source",
"datasource": "Data Source",
"more": "المزيد",
"less": "أقل",
"event": "حدث",
@ -54,12 +136,14 @@
"after": "بعد",
"before": "قبل",
"search": "البحث",
"searchIn": "Search In",
"notification": "إشعار",
"reference": "مرجع",
"function": "وظيفة",
"confirm": "تأكيد",
"generate": "توليد",
"copy": "نسخ",
"are": "are",
"misc": "متفرقات",
"lock": "قفل",
"unlock": "فتح",
@ -76,9 +160,39 @@
"hideField": "Hide Field",
"sortAsc": "Sort Ascending",
"sortDesc": "Sort Descending",
"geoDataField": "GeoData Field"
"move": "Move",
"geoDataField": "GeoData Field",
"type": "Type",
"name": "Name",
"changes": "Changes",
"new": "New",
"old": "Old",
"data": "Data",
"source": "Source",
"destination": "Destination",
"active": "Active",
"inactive": "Inactive",
"linked": "linked",
"finish": "Finish",
"min": "Min",
"max": "Max",
"avg": "Avg",
"sum": "Sum",
"count": "Count",
"countDistinct": "Count Distinct",
"sumDistinct": "Sum Distinct",
"avgDistinct": "Avg Distinct",
"join": "Join",
"options": "Options",
"primaryValue": "Primary Value",
"useSurveyMode": "Use Survey Mode",
"shift": "Shift",
"enter": "Enter",
"seconds": "Seconds"
},
"objects": {
"workspace": "Workspace",
"workspaces": "Workspaces",
"project": "مشروع",
"projects": "مشاريعي",
"table": "جدول",
@ -95,6 +209,7 @@
"webhooks": "الخطافات",
"view": "عرض",
"views": "مشاهدات",
"sidebar": "Sidebar",
"viewType": {
"grid": "شبكة",
"gallery": "معرض صور",
@ -107,16 +222,27 @@
"users": "مستخدمين",
"role": "دور",
"roles": "أدوار",
"developer": "Developer",
"roleType": {
"owner": "مالك",
"creator": "منشيء",
"editor": "محرر",
"commenter": "معلق",
"viewer": "مشاهد",
"noaccess": "No Access",
"superAdmin": "Super Admin",
"orgLevelCreator": "Organization Level Creator",
"orgLevelViewer": "Organization Level Viewer"
},
"sqlVIew": "SQL View"
"sqlVIew": "SQL View",
"rowHeight": "Record Height",
"heightClass": {
"short": "Short",
"medium": "Medium",
"tall": "Tall",
"extra": "Extra"
},
"externalDb": "External Database"
},
"datatype": {
"ID": "هوية",
@ -171,17 +297,63 @@
"isNotNull": "ليس فارغاً"
},
"title": {
"docs": "Docs",
"forum": "Forum",
"parameter": "Parameter",
"headers": "Headers",
"parameterName": "Parameter Name",
"currencyLocale": "Currency Locale",
"currencyCode": "Currency Code",
"searchMembers": "Search Members",
"noMembersFound": "No members found",
"dateJoined": "Date Joined",
"tokenName": "Token name",
"inDesktop": "in Desktop",
"rowData": "Record data",
"creator": "Creator",
"qrCode": "QR Code",
"termsOfService": "Terms of Service",
"updateSelectedRows": "Update Selected Records",
"noFiltersAdded": "No filters added",
"editCards": "Edit Cards",
"noFieldsFound": "No fields found",
"displayValue": "Display Value",
"expand": "Expand",
"hideAll": "Hide all",
"hideSystemFields": "Hide system fields",
"removeFile": "Remove File",
"hasMany": "Has Many",
"manyToMany": "Many to Many",
"virtualRelation": "Virtual Relation",
"linkMore": "Link More",
"linkMoreRecords": "Link more records",
"downloadFile": "Download File",
"renameTable": "Rename Table",
"renamingTable": "Renaming Table",
"renamingWs": "Renaming Workspace",
"renameWs": "Rename Workspace",
"deleteWs": "Delete Workspace",
"deletingWs": "Deleting Workspace",
"copyAuthToken": "Copy Auth Token",
"copiedAuthToken": "Copied Auth Token",
"copyInviteToken": "Copy Invite Token",
"showSidebar": "Show Sidebar",
"hideSidebar": "Hide Sidebar",
"creatingTable": "Creating Table",
"erdView": "ERD View",
"newBase": "New Data Source",
"newProj": "مشروع جديد",
"createBase": "Create Base",
"myProject": "مشاريعي",
"formTitle": "عنوان النموذج",
"collabView": "عرض تعاوني",
"lockedView": "عرض مغلق",
"personalView": "عرض شخصي",
"collaborative": "Collaborative",
"locked": "Locked",
"personal": "Personal",
"appStore": "متجر التطبيقات",
"teamAndAuth": "الفريق والمصادقة",
"rolesUserMgmt": "الأدوار وإدارة المستخدمين",
"userMgmt": "إدارة المستخدمين",
"apiTokens": "API Tokens",
"apiTokenMgmt": "إدارة رموز API",
"rolesMgmt": "إدارة الأدوار",
"projMeta": "البيانات الوصفية للمشروع",
@ -204,20 +376,129 @@
"generateToken": "إنشاء الرمز المميز",
"APIsAndSupport": "APIs & الدعم",
"helpCenter": "مركز المساعدة",
"noLabels": "No Labels",
"swaggerDocumentation": "Swagger Documentation",
"quickImportFrom": "استيراد سريع من",
"quickImport": "استيراد سريع",
"quickImportAirtable": "Quick Import - Airtable",
"quickImportCSV": "Quick Import - CSV",
"quickImportExcel": "Quick Import - Excel",
"quickImportJSON": "Quick Import - JSON",
"jsonEditor": "JSON Editor",
"comingSoon": "Coming Soon",
"advancedSettings": "الإعدادات المتقدمة",
"codeSnippet": "كتلة برمجية",
"keyboardShortcut": "Keyboard Shortcuts",
"generateRandomName": "Generate Random Name",
"findRowByScanningCode": "Find row by scanning a QR or Barcode"
"findRowByScanningCode": "Find row by scanning a QR or Barcode",
"tokenManagement": "Token Management",
"addNewToken": "Add new token",
"accountSettings": "Account Settings",
"resetPasswordMenu": "Reset Password",
"tokens": "Tokens",
"userManagement": "User Management",
"accountManagement": "Account management",
"licence": "Licence",
"allowAllMimeTypes": "Allow All Mime Types",
"defaultView": "Default View",
"relations": "Relations",
"switchLanguage": "Switch Language",
"renameFile": "Rename File",
"links": {
"noAction": "No Action",
"cascade": "Cascade",
"restrict": "Restrict",
"setNull": "Set NULL",
"setDefault": "Set Default"
}
},
"labels": {
"heading1": "Heading 1",
"heading2": "Heading 2",
"heading3": "Heading 3",
"bold": "Bold",
"italic": "Italic",
"underline": "Underline",
"strike": "Strike",
"taskList": "Task List",
"bulletList": "Bullet List",
"numberedList": "Numbered List",
"downloadData": "Download Data",
"blockQuote": "Block Quote",
"noToken": "No Token",
"tokenLimit": "Only one token per user is allowed",
"duplicateAttachment": "File with name {filename} already attached",
"viewIdColon": "VIEW ID: {viewId}",
"toAddress": "To Address",
"subject": "Subject",
"body": "Body",
"commaSeparatedMobileNumber": "Comma separated Mobile #",
"headerName": "Header Name",
"icon": "Icon",
"max": "Max",
"enableRichText": "Enable Rich Text",
"idColon": "Id:",
"copiedRecordURL": "Copied Record URL",
"copyRecordURL": "Copy Record URL",
"duplicateRecord": "Duplicate record",
"binaryEncodingFormat": "Binary encoding format",
"syntax": "Syntax",
"examples": "Examples",
"durationInfo": "A duration of time in minutes or seconds (e.g. 1:23).",
"addHeader": "Add Header",
"enterDefaultUrlOptional": "Enter default URL (Optional)",
"negative": "Negative",
"discard": "Discard",
"default": "Default",
"defaultNumberPercent": "Default Number (%)",
"durationFormat": "Duration Format",
"dateFormat": "Date Format",
"timeFormat": "Time Format",
"singularLabel": "Singular Label",
"pluralLabel": "Plural Label",
"optional": "(Optional)",
"clickToMake": "Click to make",
"visibleForRole": "visible for role:",
"inUI": "in UI Dashboard",
"projectSettings": "Base Settings",
"clickToHide": "Click to hide",
"clickToDownload": "Click to download",
"forRole": "for role",
"clickToCopyViewID": "Click to copy View ID",
"viewMode": "View Mode",
"searchUsers": "Search Users",
"superAdmin": "Super Admin",
"allTables": "All Tables",
"members": "Members",
"dataSources": "Data Sources",
"connectDataSource": "Connect a Data Source",
"searchProjects": "Search Bases",
"createdBy": "Created By",
"viewingAttachmentsOf": "Viewing Attachments of",
"readOnly": "Readonly",
"dropHere": "Drop here",
"createdOn": "Created On",
"notifyVia": "إعلام عبر",
"projName": "اسم المشروع",
"profile": "Profile",
"accountDetails": "Account Details",
"controlAppearance": "Control your Appearance.",
"accountEmailID": "Account Email ID",
"backToWorkspace": "Back to Workspace",
"untitledToken": "Untitled token",
"tableName": "اسم الجدول",
"dashboardName": "Dashboard name",
"createView": "Create a View",
"creatingView": "Creating View",
"duplicateView": "Duplicate View",
"duplicateGridView": "Duplicate Grid View",
"createGridView": "Create Grid View",
"duplicateGalleryView": "Duplicate Gallery View",
"createGalleryView": "Create Gallery View",
"duplicateFormView": "Duplicate Form View",
"createFormView": "Create Form View",
"duplicateKanbanView": "Duplicate Kanban View",
"createKanbanView": "Create Kanban View",
"viewName": "عرض الاسم",
"viewLink": "عرض الرابط",
"columnName": "اسم العمود",
@ -247,6 +528,14 @@
"where": "أين",
"cache": "ذاكرة التخزين المؤقت",
"chat": "دردشة",
"showOrHide": "Show or Hide",
"airtable": "Airtable",
"csv": "CSV",
"csvFile": "CSV File",
"json": "JSON",
"jsonFile": "JSON File",
"excel": "Excel",
"microsoftExcel": "Microsoft Excel",
"email": "البريد الالكتروني",
"storage": "التخزين",
"uiAcl": "UI-ACL",
@ -255,6 +544,7 @@
"created": "إنشاء",
"sqlOutput": "إخراج SQL",
"addOption": "إضافة خيار",
"interfaceColor": "Interface Color",
"qrCodeValueColumn": "Column with QR code value",
"barcodeValueColumn": "Column with Barcode value",
"barcodeFormat": "Barcode format",
@ -282,13 +572,17 @@
"joinDiscord": "انضم إلى Discord",
"joinCommunity": "انضم إلى مجتمع NocoDB",
"joinReddit": "انضم إلى /r/NocodB",
"followNocodb": "تابع NocoDB"
"followNocodb": "تابع NocoDB",
"communityTranslated": "(Community Translated)"
},
"twitter": "Twitter",
"docReference": "مرجع الوثيقة",
"selectUserRole": "حدد دور المستخدم",
"childTable": "جدول فرعي",
"childColumn": "عمود فرعي",
"childField": "Child field",
"linkToAnotherRecord": "Link to another record",
"links": "Links",
"onUpdate": "عند التحديث",
"onDelete": "عند الحذف",
"account": "حساب",
@ -298,16 +592,21 @@
"customTheme": "سمة مخصصة",
"requestDataSource": "طلب مصدر البيانات الذي تحتاجه؟",
"apiKey": "مفتاح API",
"sharedBase": "قاعدة مشتركة",
"personalAccessToken": "Personal Access Token",
"sharedBaseUrl": "Shared Base URL",
"importData": "استيراد البيانات",
"importSecondaryViews": "استيراد المشاهدات الثانوية",
"importRollupColumns": "استيراد الأعمدة المتدحرجة",
"importLookupColumns": "استيراد أعمدة البحث",
"importAttachmentColumns": "استيراد أعمدة المرفق",
"importFormulaColumns": "استيراد أعمدة الصيغة",
"importUsers": "Import Users (by email)",
"noData": "لا توجد بيانات",
"goToDashboard": "الذهاب إلى لوحة التحكم",
"importing": "الاستيراد",
"formatJson": "Format JSON",
"autoSelectFieldTypes": "Auto-Select Field Types",
"firstRowAsHeaders": "Use First Record as Headers",
"flattenNested": "متداخلة متقطعة",
"downloadAllowed": "التحميل المسموح به",
"weAreHiring": "نحن نوظف!",
@ -325,9 +624,61 @@
"welcomeToNc": "مرحبا بكم في NocoDB!",
"inviteOnlySignup": "Allow signup only using invite url",
"nextRow": "Next Row",
"prevRow": "Previous Row"
"prevRow": "Previous Row",
"addRowGrid": "Manually add data in grid view",
"addRowForm": "Enter record data through a form",
"noAccess": "No access",
"restApis": "Rest APIs",
"apis": "APIs",
"includeData": "Include Data",
"includeView": "Include View",
"includeWebhook": "Include Webhook",
"zoomInToViewColumns": "Zoom in to view columns",
"embedInSite": "Embed this view in your site",
"titleRequired": "title is required.",
"sourceNameRequired": "Source name is required",
"changeWsName": "Change Workspace Name",
"pressEnter": "Press Enter",
"newFormLoaded": "New form will be loaded after"
},
"activity": {
"openInANewTab": "Open in a new tab",
"copyIFrameCode": "Copy IFrame code",
"onCondition": "On Condition",
"bulkDownload": "Bulk Download",
"attachFile": "Attach File",
"viewAttachment": "View Attachments",
"attachmentDrop": "Click or drop a file into cell",
"addFiles": "Add File(s)",
"hideInUI": "Hide in UI",
"addBase": "Add Base",
"addParameter": "Add Parameter",
"submitAnotherForm": "Submit Another Form",
"dragAndDropFieldsHereToAdd": "Drag and drop fields here to add",
"editSource": "Edit Data Source",
"enterText": "Enter text",
"okEditBase": "Ok & Edit Base",
"showInUI": "Show in UI",
"outOfSync": "Out of sync",
"newSource": "New Data Source",
"newWebhook": "New Webhook",
"enablePublicAccess": "Enable Public Access",
"doYouWantToSaveTheChanges": "Do you want to save the changes ?",
"editingAccess": "Editing access",
"enabledPublicViewing": "Enable public viewing",
"restrictAccessWithPassword": "Restrict access with password",
"manageProjectAccess": "Manage Base Access",
"allowDownload": "Allow Download",
"surveyMode": "Survey Mode",
"rtlOrientation": "RTL Orientation",
"useTheme": "Use Theme",
"copyLink": "Copy Link",
"copiedLink": "Link Copied",
"copyInviteLink": "Copy invite link",
"copiedInviteLink": "Copied invite link",
"copyUrl": "نسخ الرابط",
"moreColors": "More Colors",
"moveProject": "Move Base",
"createProject": "إنشاء مشروع",
"importProject": "استيراد مشروع",
"searchProject": "البحث عن مشروع",
@ -338,6 +689,7 @@
"deleteProject": "حذف المشروع",
"refreshProject": "تحديث المشاريع",
"saveProject": "حفظ المشروع",
"saveAndQuit": "Save & Quit",
"deleteKanbanStack": "Delete stack?",
"createProjectExtended": {
"extDB": "إنشاء عن طريق ربط <br> قاعدة بيانات خارجية",
@ -353,6 +705,7 @@
"translate": "مساعدة ترجمة",
"account": {
"authToken": "نسخ Auth Token",
"authTokenCopied": "Copied Auth Token",
"swagger": "Swagger: REST APIs",
"projInfo": "نسخ معلومات المشروع",
"themes": "مظاهر"
@ -362,7 +715,10 @@
"filter": "تصفية",
"addFilter": "إضافة تصفية",
"share": "مشاركة",
"groupBy": "Group By",
"addSubGroup": "Add subgroup",
"shareBase": {
"label": "Share base",
"disable": "تعطيل قاعدة مشتركة",
"enable": "أي شخص لديه الرابط",
"link": "رابط قاعدة مشتركة"
@ -372,6 +728,8 @@
"inviteTeam": "دعوة فريق",
"inviteUser": "Invite User",
"inviteToken": "رمز دعوة",
"linkedRecords": "Linked Records",
"addNewLink": "Add New Link",
"newUser": "مستخدم جديد",
"editUser": "تحرير مستخدم",
"deleteUser": "إزالة المستخدم من المشروع",
@ -386,8 +744,11 @@
"previousRecord": "السجل السابق",
"copyApiURL": "نسخ رابط API",
"createTable": "Create New Table",
"createDashboard": "Create Dashboard",
"createWorkspace": "Create Workspace",
"refreshTable": "تحديث الجدول",
"renameTable": "Rename Table",
"renameLayout": "Layout Rename",
"deleteTable": "Delete Table",
"addField": "إضافة حقل جديد إلى هذا الجدول",
"setDisplay": "Set as Display value",
@ -398,6 +759,9 @@
"insertRow": "إدراج صف جديد",
"duplicateRow": "Duplicate Row",
"deleteRow": "حذف الصف",
"deleteRows": "Delete records",
"predictColumns": "Predict Fields",
"predictFormulas": "Predict Formulas",
"deleteSelectedRow": "حذف الصفوف المحددة",
"importExcel": "استيراد Excel",
"importCSV": "استيراد CSV",
@ -418,6 +782,7 @@
"ListView": "قائمة المشاهدات",
"copyView": "نسخ العرض",
"renameView": "إعادة تسمية عرض",
"uploadData": "Upload Data",
"deleteView": "حذف العرض",
"createGrid": "إنشاء عرض الشبكة",
"createGallery": "إنشاء عرض المعرض",
@ -425,7 +790,6 @@
"createKanban": "إنشاء عرض كانبان",
"createForm": "إنشاء عرض النموذج",
"showSystemFields": "إظهار حقول النظام",
"copyUrl": "نسخ الرابط",
"openTab": "افتح علامة تبويب جديدة",
"iFrame": "انسخ كود HTML القابل للتضمين",
"addWebhook": "إضافة Webhook جديد",
@ -451,10 +815,24 @@
"addFilterGroup": "إضافة مجموعة عوامل التصفية",
"linkRecord": "اربط سجل",
"addNewRecord": "إضافة سجل جديد",
"newRecord": "New record",
"tableNameCreateNewRecord": "{tableName}: Create new record",
"gotSavedLinkedSuccessfully": "{tableName} '{recordTitle}' got saved & linked successfully",
"recordCreatedLinked": "Record Created & Linked",
"useConnectionUrl": "استخدام رابط الاتصال",
"toggleCommentsDraw": "تبديل سحب التعليقات",
"expandRecord": "Expand Record",
"deleteRecord": "Delete Record",
"fullWidth": "Full width",
"exitFullWidth": "Exit full width",
"markAllAsRead": "Mark all as read",
"column": {
"delete": "Delete Field",
"addNumber": "Add Number Field",
"addSingleLineText": "Add SingleLineText Field",
"addLongText": "Add LongText Field",
"addOther": "Add Other Field"
},
"erd": {
"showColumns": "Show Columns",
"showPkAndFk": "Show Primary and Foreign Keys",
@ -475,9 +853,11 @@
"openInGoogleMaps": "Google Maps",
"openInOpenStreetMap": "OSM"
},
"toggleMobileMode": "Toggle Mobile Mode"
"toggleMobileMode": "Toggle Mobile Mode",
"startCommenting": "Start commenting!"
},
"tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment",
"saveChanges": "حفظ التغييرات",
"xcDB": "إنشاء مشروع جديد",
"extDB": "يدعم MySQL ، PostgreSQL ، SQL Server و SQLite",
@ -488,6 +868,7 @@
"light": "هل تأتي باللون الأسود ؟ (^⇧B)"
},
"addTable": "إضافة جدول جديد",
"addDashboard": "Add new Dashboard",
"inviteMore": "دعوة المزيد من المستخدمين",
"toggleNavDraw": "تبديل درج التنقل",
"reloadApiToken": "إعادة تحميل رموز API",
@ -506,7 +887,19 @@
"clientCA": "حدد ملف CA"
},
"placeholder": {
"selectSlackChannels": "Select Slack channels",
"selectTeamsChannels": "Select Microsoft Teams channels",
"selectDiscordChannels": "Select Discord channels",
"selectMattermostChannels": "Select Mattermost channels",
"webhookTitle": "Webhook Title",
"barcodeColumn": "Select a field for the Barcode value",
"notFoundContent": "No valid field Type can be found.",
"selectBarcodeFormat": "Select a Barcode format",
"projName": "أدخل اسم المشروع",
"selectGroupField": "Select a Grouping Field",
"selectGroupFieldNotFound": "No Single Select Field can be found. Please create one first.",
"selectGeoField": "Select a GeoData Field",
"selectGeoFieldNotFound": "No GeoData Field can be found. Please create one first.",
"password": {
"enter": "أدخل كلمة المرور",
"current": "كلمة المرور الحالية",
@ -514,6 +907,8 @@
"save": "حفظ كلمة المرور",
"confirm": "تأكيد كلمة المرور الجديدة"
},
"selectAColumnForTheQRCodeValue": "Select a field for the QR code value",
"allowNegativeNumbers": "Allow negative numbers",
"searchProjectTree": "جداول البحث",
"searchFields": "حقول البحث",
"searchColumn": "بحث {بحث} عمود",
@ -523,19 +918,137 @@
"defaultValue": "القيمة الافتراضية",
"filterByEmail": "تصفية عن طريق البريد الإلكتروني",
"filterQuery": "إستعلام الفلتر",
"selectField": "حدد حقل"
"selectField": "حدد حقل",
"precision": "Precision",
"decimal1": "1.0",
"decimal2": "1.00",
"decimal3": "1.000",
"decimal4": "1.0000",
"decimal5": "1.00000",
"decimal6": "1.000000",
"decimal7": "1.0000000",
"decimal8": "1.00000000",
"value": "Value",
"key": "Key"
},
"msg": {
"clickToCopyFieldId": "Click to copy Field Id",
"enterPassword": "Enter password",
"bySigningUp": "By signing up, you agree to the",
"subscribeToOurWeeklyNewsletter": "Subscribe to our weekly newsletter",
"verifyingPassword": "Verifying Password",
"thisSharedViewIsProtected": "This shared view is protected",
"successfullySubmittedFormData": "Successfully submitted form data",
"formViewNotSupportedOnMobile": "Form view is not supported on mobile",
"newFormWillBeLoaded": "New form will be loaded after {seconds} seconds",
"optimizedQueryDisabled": "Optimized query is disabled",
"optimizedQueryEnabled": "Optimized query is enabled",
"lookupNonBtWarning": "Lookup field is not supported for non-Belongs to relation",
"invalidTime": "Invalid Time",
"linkColumnClearNotSupportedYet": "You don't have any supported links for Lookup",
"recordCouldNotBeFound": "Record could not be found",
"invalidPhoneNumber": "Invalid phone number",
"pageSizeChanged": "Page size changed",
"errorLoadingData": "Error loading data",
"webhookBodyMsg1": "Use context variable",
"webhookBodyMsg2": "body",
"webhookBodyMsg3": "to refer the record under consideration",
"formula": {
"hintStart": "Hint: Use {placeholder1} to reference fields, e.g: {placeholder2}. For more, please check out",
"hintEnd": "Formulas.",
"noSuggestedFormulaFound": "No suggested formula found",
"numericTypeIsExpected": "Numeric type is expected",
"stringTypeIsExpected": "String type is expected",
"operationNotAvailable": "{operation} operation not available",
"cantSaveFieldFormulaInvalid": "Can’t save field because formula is invalid",
"notSupportedToReferenceColumn": "Not supported to reference field {columnName}",
"typeIsExpectedButFound": "Type {type} is expected but found Type {found}",
"requiredArgumentsFormula": "{calleeName} requires {requiredArguments} arguments",
"minRequiredArgumentsFormula": "{calleeName} required minimum {minRequiredArguments} arguments",
"maxRequiredArgumentsFormula": "{calleeName} required maximum {maxRequiredArguments} arguments",
"functionNotAvailable": "{function} function is not available",
"firstParamWeekDayHaveDate": "The first parameter of WEEKDAY() should have date value",
"secondParamWeekDayHaveDate": "The second parameter of WEEKDAY() should have the value either \"sunday\", \"monday\", \"tuesday\", \"wednesday\", \"thursday\", \"friday\" or \"saturday\"",
"firstParamDateAddHaveDate": "The first parameter of DATEADD() should have date value",
"secondParamDateAddHaveNumber": "The second parameter of DATEADD() should have numeric value",
"thirdParamDateAddHaveDate": "The third parameter of DATEADD() should have the value either \"day\", \"week\", \"month\" or \"year\"",
"firstParamDateDiffHaveDate": "The first parameter of DATEDIFF() should have date value",
"secondParamDateDiffHaveDate": "The second parameter of DATEDIFF() should have date value",
"thirdParamDateDiffHaveDate": "The third parameter of DATETIME_DIFF() should have value either \"milliseconds\", \"ms\", \"seconds\", \"s\", \"minutes\", \"m\", \"hours\", \"h\", \"days\", \"d\", \"weeks\", \"w\", \"months\", \"M\", \"quarters\", \"Q\", \"years\", or \"y\"",
"columnNotAvailable": "Field {columnName} is not available",
"cantSaveCircularReference": "Can’t save field because it causes a circular reference",
"columnWithTypeFoundButExpected": "Field {columnName} with {columnType} type is found but {expectedType} type is expected",
"columnNotMatchedWithType": "{columnName} is not matched with {columnType}"
},
"selectOption": {
"cantBeNull": "Select options can't be null",
"multiSelectCantHaveCommas": "MultiSelect fields can't have commas(',')",
"cantHaveDuplicates": "Select options can't have duplicates",
"createNewOptionNamed": "Create new option named"
},
"plsEnterANumber": "Please enter a number",
"plsInputEmail": "Please input email",
"invalidDate": "Invalid date",
"invalidLocale": "Invalid locale",
"invalidCurrencyCode": "Invalid Currency Code",
"postgresHasItsOwnCurrencySettings": "PostgreSQL 'money' type has own currency settings",
"validColumnsForBarCode": "The valid Field Types for a Barcode Field are: Number, Single Line Text, Long Text, Phone Number, URL, Email, Decimal. Please create one first.",
"hm": {
"title": "Has Many Relation",
"tooltip_desc": "A single record from table ",
"tooltip_desc2": " can be linked with multiple records from table "
},
"mm": {
"title": "Many to Many Relation",
"tooltip_desc": "Multiple records from table ",
"tooltip_desc2": " can be linked with multiple records from table "
},
"bt": {
"title": "Belongs to Relation",
"tooltip_desc": "A single record from table ",
"tooltip_desc2": " can be linked with a record from table "
},
"oo": {
"title": "One to One Relation",
"tooltip_desc": "A single record from table ",
"tooltip_desc2": " can be linked with a single record from table "
},
"noRecordsAreLinkedFromTable": "No records are linked from table",
"noRecordsLinked": "No records linked",
"recordsLinked": "records linked",
"acceptOnlyValid": "Accepts only",
"apiTokenCreate": "Create personal API tokens to use in automation or external apps.",
"selectFieldToSort": "Select Field to Sort",
"thereAreNoRecordsInTable": "There are no records in table",
"createWebhookMsg1": "Get started with web-hooks!",
"createWebhookMsg2": "Create web-hooks to power you automations,",
"createWebhookMsg3": "Get notified as soon as there are changes in your data",
"areYouSureUWantTo": "Are you sure you want to delete the following",
"areYouSureUWantToDeleteLabel": "Are you sure you want to {deleteLabel} the following",
"idColumnRequired": "ID field is required, you can rename this later if required.",
"length59Required": "The length exceeds the max 59 characters",
"noNewNotifications": "You have no new notifications",
"noRecordFound": "Record not found",
"rowDeleted": "Record deleted",
"saveChanges": "Do you want to save the changes?",
"tooLargeFieldEntity": "The field is too large to be converted to {entity}",
"roleRequired": "Role required",
"warning": {
"dbValid": "Please make sure database you are trying to connect is valid! This operation can cause schema loss!!",
"barcode": {
"renderError": "Barcode error - please check compatibility between input and barcode type"
},
"nonEditableFields": {
"computedFieldUnableToClear": "Warning: Computed field - unable to clear text",
"qrFieldsCannotBeDirectlyChanged": "Warning: QR fields cannot be directly changed."
}
"qrFieldsCannotBeDirectlyChanged": "Warning: QR fields cannot be directly changed.",
"barcodeFieldsCannotBeDirectlyChanged": "Warning: Barcode fields cannot be directly changed."
},
"duplicateProject": "Are you sure you want to duplicate the base?",
"duplicateTable": "Are you sure you want to duplicate the table?"
},
"info": {
"disabledAsViewLocked": "Disabled as View is locked",
"basesMigrated": "Bases are migrated. Please try again.",
"pasteNotSupported": "Paste operation is not supported on the active cell",
"roles": {
"orgCreator": "Creator can create new projects and access any invited project.",
@ -640,6 +1153,9 @@
"tablesMetadataInSync": "تزامن البيانات الوصفية للجداول",
"addMultipleUsers": "يمكنك إضافة أكثر من فاصلة (,) لفصل الإيميلات",
"enterTableName": "أدخل اسم الجدول",
"enterLayoutName": "Enter Layout name",
"enterDashboardName": "Enter Dashboard name",
"defaultColumns": "Default fields",
"addDefaultColumns": "إضافة الأعمدة الافتراضية",
"tableNameInDb": "اسم الجدول كما تم حفظه في قاعدة البيانات",
"airtable": {
@ -662,8 +1178,10 @@
"valueAlreadyInList": "هذه القيمة موجودة مسبقاً في القائمة",
"noColumnsToUpdate": "لا توجد أعمدة للتحديث",
"tableDeleted": "تم حذف الجدول بنجاح",
"layoutDeleted": "Deleted layout successfully",
"generatePublicShareableReadonlyBase": "إنشاء قاعدة للقراءة فقط قابلة للمشاركة العامة",
"deleteViewConfirmation": "هل أنت متأكد من أنك تريد حذف هذا العرض؟",
"deleteLayoutConfirmation": "Are you sure you want to delete this Layout?",
"deleteTableConfirmation": "هل تريد حذف الجدول",
"showM2mTables": "إظهار جداول M2M",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
@ -674,18 +1192,40 @@
"deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",
"noMoreRecords": "No more records"
"noMoreRecords": "No more records",
"tokenNameNotEmpty": "Token name should not be empty",
"tokenNameMaxLength": "Token name should not be more than 255 characters",
"dbNameRequired": "Database name is required",
"wsNameRequired": "Workspace name required",
"wsNameMinLength": "Workspace name must be at least 3 characters long",
"wsNameMaxLength": "Workspace name must be at most 50 characters long",
"wsDeleteDlg": "Delete this workspace and all it’s contents.",
"userConfirmation": "I understand that this action is irreversible",
"pageNotFound": "Page Not Found",
"makeLineBreak": "to make a line break",
"goToPrevious": "Go to previous",
"goToNext": "Go to next",
"thankYou": "Thank you!",
"submittedFormData": "You have successfully submitted the form data."
},
"error": {
"nameRequired": "Name Required",
"nameMinLength": "Name must be at least 2 characters long",
"nameMaxLength": "Name must be at most 60 characters long",
"viewNameRequired": "View name is required",
"nameMaxLength256": "Name must be at most 256 characters long",
"viewNameUnique": "View name should be unique",
"searchProject": "البحث عن {بحث} لم يتم العثور على نتائج",
"invalidChar": "حرف غير صالح في مسار المجلد.",
"invalidDbCredentials": "بيانات اعتماد قاعدة بيانات غير صالحة.",
"unableToConnectToDb": "غير قادر على الاتصال بقاعدة البيانات ، يرجى التحقق من قاعدة البيانات الخاصة بك.",
"invalidYear": "Invalid year",
"userDoesntHaveSufficientPermission": "المستخدم غير موجود أو لديه إذن كاف لإنشاء مخطط.",
"dbConnectionStatus": "معلمات قاعدة البيانات غير صالحة",
"dbConnectionFailed": "فشل الاتصال:",
"nullFilterExists": "Null filter exists. Please remove them",
"signUpRules": {
"emailReqd": "البريد الالكتروني مطلوب",
"emailRequired": "Email is required",
"emailInvalid": "يجب أن يكون البريد الإلكتروني صالحا",
"passwdRequired": "كلمة المرور مطلوبة",
"passwdLength": "يجب أن تكون كلمة المرور الخاصة بك 8 أحرف على الأقل",
@ -695,7 +1235,9 @@
"atLeastOneUppercase": "حرف كبير واحد",
"atLeastOneNumber": "رقم واحد",
"atLeastOneSpecialChar": "حرف خاص واحد",
"allowedSpecialCharList": "قائمة الأحرف الخاصة المسموح بها"
"allowedSpecialCharList": "قائمة الأحرف الخاصة المسموح بها",
"invalidEmails": "Invalid emails",
"invalidEmail": "Invalid Email"
},
"invalidURL": "رابط غير صالح",
"invalidEmail": "Invalid Email",
@ -726,6 +1268,8 @@
"nameShouldStartWithAnAlphabetOr_": "Name should start with an alphabet or _",
"followingCharactersAreNotAllowed": "Following characters are not allowed",
"columnNameRequired": "Column name is required",
"duplicateColumnName": "Duplicate field name",
"uiDataTypeRequired": "UI data type is required",
"columnNameExceedsCharacters": "The length of column name exceeds the max {value} characters",
"projectNameExceeds50Characters": "Project name exceeds 50 characters",
"projectNameCannotStartWithSpace": "Project name cannot start with space",
@ -758,6 +1302,7 @@
"futureRelease": "قريبا!"
},
"success": {
"licenseKeyUpdated": "License Key Updated",
"columnDuplicated": "Column duplicated successfully",
"rowDuplicatedWithoutSavedYet": "Row duplicated (not saved)",
"updatedUIACL": "تم تحديث ACL واجهة المستخدم للجداول بنجاح",
@ -765,6 +1310,7 @@
"pluginSettingsSaved": "تم حفظ إعدادات الإضافة بنجاح",
"pluginTested": "تم اختبار إعدادات الإضافات بنجاح",
"tableRenamed": "تمت إعادة تسمية الجدول بنجاح",
"layoutRenamed": "Layout renamed successfully",
"viewDeleted": "تم حذف العرض بنجاح",
"primaryColumnUpdated": "تم التحديث بنجاح كعمود أساسي",
"tableDataExported": "تم تصدير جميع بيانات الجدول بنجاح",

580
packages/nc-gui/lang/bn_IN.json

@ -1,5 +1,45 @@
{
"dashboards": {
"create_new_dashboard_project": "Create New Interface",
"connect_data_sources": "Connect data sources",
"alert": "Alert",
"alert-message": "No databases have been connected. Connect database bases to build interfaces. Skip this step and add databases from the base home page later.",
"select_database_projects_that_you_want_to_link_to_this_dashboard_projects": "Select Database Bases that you want to link to this Interface.",
"create_interface": "Create interface",
"project_name": "Base Name",
"connect": "Connect",
"buttonActionTypes": {
"open_external_url": "Open external link",
"delete_record": "Delete record",
"update_record": "Update record",
"open_layout": "Open layout"
},
"widgets": {
"static_text": "Text",
"chart": "Chart",
"table": "Table",
"image": "Image",
"map": "Map",
"button": "Button",
"number": "Number",
"bar_chart": "Bar Chart",
"line_chart": "Line Chart",
"area_chart": "Area Chart",
"pie_chart": "Pie Chart",
"donut_chart": "Donut Chart",
"scatter_plot": "Scatter Plot",
"bubble_chart": "Bubble Chart",
"radar_chart": "Radar Chart",
"polar_area_chart": "Polar Area Chart",
"radial_bar_chart": "Radial Bar Chart",
"heatmap_chart": "Heatmap Chart",
"treemap_chart": "Treemap Chart",
"box_plot_chart": "Box Plot Chart",
"candlestick_chart": "Candlestick Chart"
}
},
"general": {
"quit": "Quit",
"home": "বি",
"load": "ভর",
"open": "খ",
@ -7,27 +47,67 @@
"yes": "হ",
"no": "ন",
"ok": "ঠিক আছ",
"back": "Back",
"and": "এব",
"or": "ব",
"add": "যগ করন",
"edit": "সমদন",
"link": "Link",
"links": "Links",
"remove": "অপসরণ",
"import": "Import",
"logout": "Log Out",
"empty": "Empty",
"changeIcon": "Change Icon",
"save": "সরকষণ",
"available": "Available",
"abort": "Abort",
"saving": "Saving",
"cancel": "বিল",
"null": "Null",
"escape": "Escape",
"hex": "Hex",
"clear": "Clear",
"slack": "Slack",
"comment": "Comment",
"microsoftTeams": "Microsoft Teams",
"discord": "Discord",
"matterMost": "Mattermost",
"twilio": "Twilio",
"whatsappTwilio": "WhatsApp Twilio",
"quote": "Quote",
"submit": "জমিন",
"create": "সি",
"createEntity": "Create {entity}",
"creating": "Creating",
"creatingEntity": "Creating {entity}",
"details": "Details",
"skip": "Skip",
"code": "Code",
"duplicate": "Duplicate",
"duplicating": "Duplicating",
"activate": "Activate",
"action": "Action",
"insert": "Insert",
"delete": "ম",
"deleteEntity": "Delete {entity}",
"bulkInsert": "Bulk Insert",
"bulkDelete": "Bulk Delete",
"bulkUpdate": "Bulk Update",
"deleting": "Deleting",
"update": "হলনদ",
"rename": "নম পরিবরতন",
"reload": "পনরড",
"reset": "রিট",
"install": "ইনসটল করন",
"show": "শ",
"access": "Access",
"visibility": "Visibility",
"hide": "লন",
"deprecated": "Deprecated",
"showAll": "সব দও",
"hideAll": "সব লও",
"notFound": "Not found",
"showMore": "আরন",
"showOptions": "বিকলপগিন",
"hideOptions": "বিকলপগিন",
@ -47,6 +127,8 @@
"upload": "আপলড করন",
"download": "ডউনলড করন",
"default": "Default",
"base": "Source",
"datasource": "Data Source",
"more": "আরও",
"less": "কম",
"event": "ঘটন",
@ -54,12 +136,14 @@
"after": "পর",
"before": "আগ",
"search": "Search",
"searchIn": "Search In",
"notification": "বিঞপি",
"reference": "পরসঙগ",
"function": "নিিট করম",
"confirm": "Confirm",
"generate": "Generate",
"copy": "Copy",
"are": "are",
"misc": "Miscellaneous",
"lock": "Lock",
"unlock": "Unlock",
@ -76,9 +160,39 @@
"hideField": "Hide Field",
"sortAsc": "Sort Ascending",
"sortDesc": "Sort Descending",
"geoDataField": "GeoData Field"
"move": "Move",
"geoDataField": "GeoData Field",
"type": "Type",
"name": "Name",
"changes": "Changes",
"new": "New",
"old": "Old",
"data": "Data",
"source": "Source",
"destination": "Destination",
"active": "Active",
"inactive": "Inactive",
"linked": "linked",
"finish": "Finish",
"min": "Min",
"max": "Max",
"avg": "Avg",
"sum": "Sum",
"count": "Count",
"countDistinct": "Count Distinct",
"sumDistinct": "Sum Distinct",
"avgDistinct": "Avg Distinct",
"join": "Join",
"options": "Options",
"primaryValue": "Primary Value",
"useSurveyMode": "Use Survey Mode",
"shift": "Shift",
"enter": "Enter",
"seconds": "Seconds"
},
"objects": {
"workspace": "Workspace",
"workspaces": "Workspaces",
"project": "পরকলপ",
"projects": "পরকলপ",
"table": "টিল",
@ -95,6 +209,7 @@
"webhooks": "ওযবহকস",
"view": "দন",
"views": "ভিউ",
"sidebar": "Sidebar",
"viewType": {
"grid": "গিড",
"gallery": "গ",
@ -107,16 +222,27 @@
"users": "বযবহরক",
"role": "ভি",
"roles": "ভি",
"developer": "Developer",
"roleType": {
"owner": "মিক",
"creator": "সরষ",
"editor": "সমদক",
"commenter": "মনতবযক",
"viewer": "দরশক",
"noaccess": "No Access",
"superAdmin": "Super Admin",
"orgLevelCreator": "Organization Level Creator",
"orgLevelViewer": "Organization Level Viewer"
},
"sqlVIew": "SQL View"
"sqlVIew": "SQL View",
"rowHeight": "Record Height",
"heightClass": {
"short": "Short",
"medium": "Medium",
"tall": "Tall",
"extra": "Extra"
},
"externalDb": "External Database"
},
"datatype": {
"ID": "আইডি",
@ -171,17 +297,63 @@
"isNotNull": "নল নয"
},
"title": {
"docs": "Docs",
"forum": "Forum",
"parameter": "Parameter",
"headers": "Headers",
"parameterName": "Parameter Name",
"currencyLocale": "Currency Locale",
"currencyCode": "Currency Code",
"searchMembers": "Search Members",
"noMembersFound": "No members found",
"dateJoined": "Date Joined",
"tokenName": "Token name",
"inDesktop": "in Desktop",
"rowData": "Record data",
"creator": "Creator",
"qrCode": "QR Code",
"termsOfService": "Terms of Service",
"updateSelectedRows": "Update Selected Records",
"noFiltersAdded": "No filters added",
"editCards": "Edit Cards",
"noFieldsFound": "No fields found",
"displayValue": "Display Value",
"expand": "Expand",
"hideAll": "Hide all",
"hideSystemFields": "Hide system fields",
"removeFile": "Remove File",
"hasMany": "Has Many",
"manyToMany": "Many to Many",
"virtualRelation": "Virtual Relation",
"linkMore": "Link More",
"linkMoreRecords": "Link more records",
"downloadFile": "Download File",
"renameTable": "Rename Table",
"renamingTable": "Renaming Table",
"renamingWs": "Renaming Workspace",
"renameWs": "Rename Workspace",
"deleteWs": "Delete Workspace",
"deletingWs": "Deleting Workspace",
"copyAuthToken": "Copy Auth Token",
"copiedAuthToken": "Copied Auth Token",
"copyInviteToken": "Copy Invite Token",
"showSidebar": "Show Sidebar",
"hideSidebar": "Hide Sidebar",
"creatingTable": "Creating Table",
"erdView": "ERD View",
"newBase": "New Data Source",
"newProj": "নতন পরকলপ",
"createBase": "Create Base",
"myProject": "আমর পরকলপ",
"formTitle": "ফরম শিম",
"collabView": "সহয দরশন",
"lockedView": "লক ভিউ",
"personalView": "বযকিগত দয",
"collaborative": "Collaborative",
"locked": "Locked",
"personal": "Personal",
"appStore": "অপ সর",
"teamAndAuth": "দল ও আথ",
"rolesUserMgmt": "ভি এবযবহরক পরিলন",
"userMgmt": "বযবহরক পরিলন",
"apiTokens": "API Tokens",
"apiTokenMgmt": "এপিআই টন পরিলন",
"rolesMgmt": "ভি পরিলন",
"projMeta": "পরকলপ ম",
@ -204,20 +376,129 @@
"generateToken": "Generate Token",
"APIsAndSupport": "APIs & Support",
"helpCenter": "Help center",
"noLabels": "No Labels",
"swaggerDocumentation": "Swagger Documentation",
"quickImportFrom": "Quick Import From",
"quickImport": "Quick Import",
"quickImportAirtable": "Quick Import - Airtable",
"quickImportCSV": "Quick Import - CSV",
"quickImportExcel": "Quick Import - Excel",
"quickImportJSON": "Quick Import - JSON",
"jsonEditor": "JSON Editor",
"comingSoon": "Coming Soon",
"advancedSettings": "Advanced Settings",
"codeSnippet": "Code Snippet",
"keyboardShortcut": "Keyboard Shortcuts",
"generateRandomName": "Generate Random Name",
"findRowByScanningCode": "Find row by scanning a QR or Barcode"
"findRowByScanningCode": "Find row by scanning a QR or Barcode",
"tokenManagement": "Token Management",
"addNewToken": "Add new token",
"accountSettings": "Account Settings",
"resetPasswordMenu": "Reset Password",
"tokens": "Tokens",
"userManagement": "User Management",
"accountManagement": "Account management",
"licence": "Licence",
"allowAllMimeTypes": "Allow All Mime Types",
"defaultView": "Default View",
"relations": "Relations",
"switchLanguage": "Switch Language",
"renameFile": "Rename File",
"links": {
"noAction": "No Action",
"cascade": "Cascade",
"restrict": "Restrict",
"setNull": "Set NULL",
"setDefault": "Set Default"
}
},
"labels": {
"heading1": "Heading 1",
"heading2": "Heading 2",
"heading3": "Heading 3",
"bold": "Bold",
"italic": "Italic",
"underline": "Underline",
"strike": "Strike",
"taskList": "Task List",
"bulletList": "Bullet List",
"numberedList": "Numbered List",
"downloadData": "Download Data",
"blockQuote": "Block Quote",
"noToken": "No Token",
"tokenLimit": "Only one token per user is allowed",
"duplicateAttachment": "File with name {filename} already attached",
"viewIdColon": "VIEW ID: {viewId}",
"toAddress": "To Address",
"subject": "Subject",
"body": "Body",
"commaSeparatedMobileNumber": "Comma separated Mobile #",
"headerName": "Header Name",
"icon": "Icon",
"max": "Max",
"enableRichText": "Enable Rich Text",
"idColon": "Id:",
"copiedRecordURL": "Copied Record URL",
"copyRecordURL": "Copy Record URL",
"duplicateRecord": "Duplicate record",
"binaryEncodingFormat": "Binary encoding format",
"syntax": "Syntax",
"examples": "Examples",
"durationInfo": "A duration of time in minutes or seconds (e.g. 1:23).",
"addHeader": "Add Header",
"enterDefaultUrlOptional": "Enter default URL (Optional)",
"negative": "Negative",
"discard": "Discard",
"default": "Default",
"defaultNumberPercent": "Default Number (%)",
"durationFormat": "Duration Format",
"dateFormat": "Date Format",
"timeFormat": "Time Format",
"singularLabel": "Singular Label",
"pluralLabel": "Plural Label",
"optional": "(Optional)",
"clickToMake": "Click to make",
"visibleForRole": "visible for role:",
"inUI": "in UI Dashboard",
"projectSettings": "Base Settings",
"clickToHide": "Click to hide",
"clickToDownload": "Click to download",
"forRole": "for role",
"clickToCopyViewID": "Click to copy View ID",
"viewMode": "View Mode",
"searchUsers": "Search Users",
"superAdmin": "Super Admin",
"allTables": "All Tables",
"members": "Members",
"dataSources": "Data Sources",
"connectDataSource": "Connect a Data Source",
"searchProjects": "Search Bases",
"createdBy": "Created By",
"viewingAttachmentsOf": "Viewing Attachments of",
"readOnly": "Readonly",
"dropHere": "Drop here",
"createdOn": "Created On",
"notifyVia": "এর মযম অবহিত করন",
"projName": "পরকলর নম",
"profile": "Profile",
"accountDetails": "Account Details",
"controlAppearance": "Control your Appearance.",
"accountEmailID": "Account Email ID",
"backToWorkspace": "Back to Workspace",
"untitledToken": "Untitled token",
"tableName": "Table name",
"dashboardName": "Dashboard name",
"createView": "Create a View",
"creatingView": "Creating View",
"duplicateView": "Duplicate View",
"duplicateGridView": "Duplicate Grid View",
"createGridView": "Create Grid View",
"duplicateGalleryView": "Duplicate Gallery View",
"createGalleryView": "Create Gallery View",
"duplicateFormView": "Duplicate Form View",
"createFormView": "Create Form View",
"duplicateKanbanView": "Duplicate Kanban View",
"createKanbanView": "Create Kanban View",
"viewName": "নম দন",
"viewLink": "লিক দন",
"columnName": "কলর নম",
@ -247,6 +528,14 @@
"where": "ক",
"cache": "ক",
"chat": "চট",
"showOrHide": "Show or Hide",
"airtable": "Airtable",
"csv": "CSV",
"csvFile": "CSV File",
"json": "JSON",
"jsonFile": "JSON File",
"excel": "Excel",
"microsoftExcel": "Microsoft Excel",
"email": "ই-মইল",
"storage": "সজ",
"uiAcl": "UI-ACL",
@ -255,6 +544,7 @@
"created": "তি",
"sqlOutput": "এসকিউএল আউটপট",
"addOption": "বিকলপ যগ করন",
"interfaceColor": "Interface Color",
"qrCodeValueColumn": "Column with QR code value",
"barcodeValueColumn": "Column with Barcode value",
"barcodeFormat": "Barcode format",
@ -282,13 +572,17 @@
"joinDiscord": "ডিসকরগ দিন",
"joinCommunity": "NocoDB কমিউনিিগ দিন",
"joinReddit": "/r/NocoDB-এ যগ দিন",
"followNocodb": "NocoDB অনসরণ করন"
"followNocodb": "NocoDB অনসরণ করন",
"communityTranslated": "(Community Translated)"
},
"twitter": "Twitter",
"docReference": "Document Reference",
"selectUserRole": "বযবহরকর ভিিচন করন",
"childTable": "Child table",
"childColumn": "Child column",
"childField": "Child field",
"linkToAnotherRecord": "Link to another record",
"links": "Links",
"onUpdate": "আপড",
"onDelete": "ডিিটএ",
"account": "Account",
@ -298,16 +592,21 @@
"customTheme": "Custom Theme",
"requestDataSource": "Request a data source you need?",
"apiKey": "API Key",
"sharedBase": "Shared Base",
"personalAccessToken": "Personal Access Token",
"sharedBaseUrl": "Shared Base URL",
"importData": "Import Data",
"importSecondaryViews": "Import Secondary Views",
"importRollupColumns": "Import Rollup Columns",
"importLookupColumns": "Import Lookup Columns",
"importAttachmentColumns": "Import Attachment Columns",
"importFormulaColumns": "Import Formula Columns",
"importUsers": "Import Users (by email)",
"noData": "No Data",
"goToDashboard": "Go to Dashboard",
"importing": "Importing",
"formatJson": "Format JSON",
"autoSelectFieldTypes": "Auto-Select Field Types",
"firstRowAsHeaders": "Use First Record as Headers",
"flattenNested": "Flatten Nested",
"downloadAllowed": "Download allowed",
"weAreHiring": "We are Hiring!",
@ -325,9 +624,61 @@
"welcomeToNc": "Welcome to NocoDB!",
"inviteOnlySignup": "Allow signup only using invite url",
"nextRow": "Next Row",
"prevRow": "Previous Row"
"prevRow": "Previous Row",
"addRowGrid": "Manually add data in grid view",
"addRowForm": "Enter record data through a form",
"noAccess": "No access",
"restApis": "Rest APIs",
"apis": "APIs",
"includeData": "Include Data",
"includeView": "Include View",
"includeWebhook": "Include Webhook",
"zoomInToViewColumns": "Zoom in to view columns",
"embedInSite": "Embed this view in your site",
"titleRequired": "title is required.",
"sourceNameRequired": "Source name is required",
"changeWsName": "Change Workspace Name",
"pressEnter": "Press Enter",
"newFormLoaded": "New form will be loaded after"
},
"activity": {
"openInANewTab": "Open in a new tab",
"copyIFrameCode": "Copy IFrame code",
"onCondition": "On Condition",
"bulkDownload": "Bulk Download",
"attachFile": "Attach File",
"viewAttachment": "View Attachments",
"attachmentDrop": "Click or drop a file into cell",
"addFiles": "Add File(s)",
"hideInUI": "Hide in UI",
"addBase": "Add Base",
"addParameter": "Add Parameter",
"submitAnotherForm": "Submit Another Form",
"dragAndDropFieldsHereToAdd": "Drag and drop fields here to add",
"editSource": "Edit Data Source",
"enterText": "Enter text",
"okEditBase": "Ok & Edit Base",
"showInUI": "Show in UI",
"outOfSync": "Out of sync",
"newSource": "New Data Source",
"newWebhook": "New Webhook",
"enablePublicAccess": "Enable Public Access",
"doYouWantToSaveTheChanges": "Do you want to save the changes ?",
"editingAccess": "Editing access",
"enabledPublicViewing": "Enable public viewing",
"restrictAccessWithPassword": "Restrict access with password",
"manageProjectAccess": "Manage Base Access",
"allowDownload": "Allow Download",
"surveyMode": "Survey Mode",
"rtlOrientation": "RTL Orientation",
"useTheme": "Use Theme",
"copyLink": "Copy Link",
"copiedLink": "Link Copied",
"copyInviteLink": "Copy invite link",
"copiedInviteLink": "Copied invite link",
"copyUrl": "কপি ইউআরএল",
"moreColors": "More Colors",
"moveProject": "Move Base",
"createProject": "পরকলপ তি করন",
"importProject": "আমদিরকলপ",
"searchProject": "অনসনন পরকলপ",
@ -338,6 +689,7 @@
"deleteProject": "পরকলপ মন",
"refreshProject": "রিশ পরকলপগি",
"saveProject": "সরকষণ পরকলপ",
"saveAndQuit": "Save & Quit",
"deleteKanbanStack": "Delete stack?",
"createProjectExtended": {
"extDB": "একটিিক ড <br> সত করি করন",
@ -353,6 +705,7 @@
"translate": "অনদ করত সহ করন",
"account": {
"authToken": "অনিি আথ টন",
"authTokenCopied": "Copied Auth Token",
"swagger": "Swagger: REST APIs",
"projInfo": "পরকলর তথয অনিি করন",
"themes": "থিম"
@ -362,7 +715,10 @@
"filter": "ছকনি",
"addFilter": "ফির যত করন",
"share": "শর",
"groupBy": "Group By",
"addSubGroup": "Add subgroup",
"shareBase": {
"label": "Share base",
"disable": "ভগ করস অকষম করন",
"enable": "লিক সহ যউ",
"link": "ভগ করস লিক"
@ -372,6 +728,8 @@
"inviteTeam": "দলক আমনরণ করন",
"inviteUser": "Invite User",
"inviteToken": "টনক আমনরণ করন",
"linkedRecords": "Linked Records",
"addNewLink": "Add New Link",
"newUser": "নতন বযবহরক",
"editUser": "বযবহরক সমদন করন",
"deleteUser": "পরকলপ থযবহরক সরন",
@ -386,8 +744,11 @@
"previousRecord": "পববরকরড",
"copyApiURL": "অনিি এপিআই ইউআরএল",
"createTable": "Create New Table",
"createDashboard": "Create Dashboard",
"createWorkspace": "Create Workspace",
"refreshTable": "টিল রিশ",
"renameTable": "Rename Table",
"renameLayout": "Layout Rename",
"deleteTable": "Delete Table",
"addField": "এই টি নতন কর যত করন",
"setDisplay": "Set as Display value",
@ -398,6 +759,9 @@
"insertRow": "নতন সিন",
"duplicateRow": "Duplicate Row",
"deleteRow": "সিন",
"deleteRows": "Delete records",
"predictColumns": "Predict Fields",
"predictFormulas": "Predict Formulas",
"deleteSelectedRow": "নিিত সিিন",
"importExcel": "একল আমদি করন",
"importCSV": "Import CSV",
@ -418,6 +782,7 @@
"ListView": "ভিউ তি",
"copyView": "অনিিন",
"renameView": "ভিউ নমকরণ",
"uploadData": "Upload Data",
"deleteView": "দয মন",
"createGrid": "গিড ভিউ তি করন",
"createGallery": "গিউ তি করন",
@ -425,7 +790,6 @@
"createKanban": "কনবন ভিউ তি করন",
"createForm": "ফরম ভিউ তি করন",
"showSystemFields": "সিম করগিন",
"copyUrl": "কপি ইউআরএল",
"openTab": "নতন টব খন",
"iFrame": "এমডযয এইচটিএমএল কড অনিি করন",
"addWebhook": "নতন ওযবহক যত করন",
@ -451,10 +815,24 @@
"addFilterGroup": "Add Filter Group",
"linkRecord": "Link record",
"addNewRecord": "Add new record",
"newRecord": "New record",
"tableNameCreateNewRecord": "{tableName}: Create new record",
"gotSavedLinkedSuccessfully": "{tableName} '{recordTitle}' got saved & linked successfully",
"recordCreatedLinked": "Record Created & Linked",
"useConnectionUrl": "Use Connection URL",
"toggleCommentsDraw": "Toggle comments draw",
"expandRecord": "Expand Record",
"deleteRecord": "Delete Record",
"fullWidth": "Full width",
"exitFullWidth": "Exit full width",
"markAllAsRead": "Mark all as read",
"column": {
"delete": "Delete Field",
"addNumber": "Add Number Field",
"addSingleLineText": "Add SingleLineText Field",
"addLongText": "Add LongText Field",
"addOther": "Add Other Field"
},
"erd": {
"showColumns": "Show Columns",
"showPkAndFk": "Show Primary and Foreign Keys",
@ -475,9 +853,11 @@
"openInGoogleMaps": "Google Maps",
"openInOpenStreetMap": "OSM"
},
"toggleMobileMode": "Toggle Mobile Mode"
"toggleMobileMode": "Toggle Mobile Mode",
"startCommenting": "Start commenting!"
},
"tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment",
"saveChanges": "परिवरतनरकित कर",
"xcDB": "একটি নতন পরকলপ তি করন",
"extDB": "মইএসকিউএল, পটগসকিউএল, এসকিউএল সর এব এসকিউএলইট সমরথন কর",
@ -488,6 +868,7 @@
"light": "এটি আস? (^⇧b)"
},
"addTable": "নতন টিল যত করন",
"addDashboard": "Add new Dashboard",
"inviteMore": "আরও বযবহরকর আমনরণ করন",
"toggleNavDraw": "টগল নিশন ডরযর",
"reloadApiToken": "এপিআই টনগিনরড করন",
@ -506,7 +887,19 @@
"clientCA": "সিএ ফইল নিচন করন"
},
"placeholder": {
"selectSlackChannels": "Select Slack channels",
"selectTeamsChannels": "Select Microsoft Teams channels",
"selectDiscordChannels": "Select Discord channels",
"selectMattermostChannels": "Select Mattermost channels",
"webhookTitle": "Webhook Title",
"barcodeColumn": "Select a field for the Barcode value",
"notFoundContent": "No valid field Type can be found.",
"selectBarcodeFormat": "Select a Barcode format",
"projName": "পরকলর নম লিন",
"selectGroupField": "Select a Grouping Field",
"selectGroupFieldNotFound": "No Single Select Field can be found. Please create one first.",
"selectGeoField": "Select a GeoData Field",
"selectGeoFieldNotFound": "No GeoData Field can be found. Please create one first.",
"password": {
"enter": "পসওযড লিন",
"current": "বরতমন পসওযড",
@ -514,6 +907,8 @@
"save": "পসওযড সরকষণ",
"confirm": "নিিত কর নতন গপননমবর"
},
"selectAColumnForTheQRCodeValue": "Select a field for the QR code value",
"allowNegativeNumbers": "Allow negative numbers",
"searchProjectTree": "টিল অনসনন করন",
"searchFields": "কর অনসনন করন",
"searchColumn": "অনসনন {অনসনন} কলম",
@ -523,19 +918,137 @@
"defaultValue": "ডিফলট মন",
"filterByEmail": "ই-মইল দির",
"filterQuery": "Filter query",
"selectField": "Select field"
"selectField": "Select field",
"precision": "Precision",
"decimal1": "1.0",
"decimal2": "1.00",
"decimal3": "1.000",
"decimal4": "1.0000",
"decimal5": "1.00000",
"decimal6": "1.000000",
"decimal7": "1.0000000",
"decimal8": "1.00000000",
"value": "Value",
"key": "Key"
},
"msg": {
"clickToCopyFieldId": "Click to copy Field Id",
"enterPassword": "Enter password",
"bySigningUp": "By signing up, you agree to the",
"subscribeToOurWeeklyNewsletter": "Subscribe to our weekly newsletter",
"verifyingPassword": "Verifying Password",
"thisSharedViewIsProtected": "This shared view is protected",
"successfullySubmittedFormData": "Successfully submitted form data",
"formViewNotSupportedOnMobile": "Form view is not supported on mobile",
"newFormWillBeLoaded": "New form will be loaded after {seconds} seconds",
"optimizedQueryDisabled": "Optimized query is disabled",
"optimizedQueryEnabled": "Optimized query is enabled",
"lookupNonBtWarning": "Lookup field is not supported for non-Belongs to relation",
"invalidTime": "Invalid Time",
"linkColumnClearNotSupportedYet": "You don't have any supported links for Lookup",
"recordCouldNotBeFound": "Record could not be found",
"invalidPhoneNumber": "Invalid phone number",
"pageSizeChanged": "Page size changed",
"errorLoadingData": "Error loading data",
"webhookBodyMsg1": "Use context variable",
"webhookBodyMsg2": "body",
"webhookBodyMsg3": "to refer the record under consideration",
"formula": {
"hintStart": "Hint: Use {placeholder1} to reference fields, e.g: {placeholder2}. For more, please check out",
"hintEnd": "Formulas.",
"noSuggestedFormulaFound": "No suggested formula found",
"numericTypeIsExpected": "Numeric type is expected",
"stringTypeIsExpected": "String type is expected",
"operationNotAvailable": "{operation} operation not available",
"cantSaveFieldFormulaInvalid": "Can’t save field because formula is invalid",
"notSupportedToReferenceColumn": "Not supported to reference field {columnName}",
"typeIsExpectedButFound": "Type {type} is expected but found Type {found}",
"requiredArgumentsFormula": "{calleeName} requires {requiredArguments} arguments",
"minRequiredArgumentsFormula": "{calleeName} required minimum {minRequiredArguments} arguments",
"maxRequiredArgumentsFormula": "{calleeName} required maximum {maxRequiredArguments} arguments",
"functionNotAvailable": "{function} function is not available",
"firstParamWeekDayHaveDate": "The first parameter of WEEKDAY() should have date value",
"secondParamWeekDayHaveDate": "The second parameter of WEEKDAY() should have the value either \"sunday\", \"monday\", \"tuesday\", \"wednesday\", \"thursday\", \"friday\" or \"saturday\"",
"firstParamDateAddHaveDate": "The first parameter of DATEADD() should have date value",
"secondParamDateAddHaveNumber": "The second parameter of DATEADD() should have numeric value",
"thirdParamDateAddHaveDate": "The third parameter of DATEADD() should have the value either \"day\", \"week\", \"month\" or \"year\"",
"firstParamDateDiffHaveDate": "The first parameter of DATEDIFF() should have date value",
"secondParamDateDiffHaveDate": "The second parameter of DATEDIFF() should have date value",
"thirdParamDateDiffHaveDate": "The third parameter of DATETIME_DIFF() should have value either \"milliseconds\", \"ms\", \"seconds\", \"s\", \"minutes\", \"m\", \"hours\", \"h\", \"days\", \"d\", \"weeks\", \"w\", \"months\", \"M\", \"quarters\", \"Q\", \"years\", or \"y\"",
"columnNotAvailable": "Field {columnName} is not available",
"cantSaveCircularReference": "Can’t save field because it causes a circular reference",
"columnWithTypeFoundButExpected": "Field {columnName} with {columnType} type is found but {expectedType} type is expected",
"columnNotMatchedWithType": "{columnName} is not matched with {columnType}"
},
"selectOption": {
"cantBeNull": "Select options can't be null",
"multiSelectCantHaveCommas": "MultiSelect fields can't have commas(',')",
"cantHaveDuplicates": "Select options can't have duplicates",
"createNewOptionNamed": "Create new option named"
},
"plsEnterANumber": "Please enter a number",
"plsInputEmail": "Please input email",
"invalidDate": "Invalid date",
"invalidLocale": "Invalid locale",
"invalidCurrencyCode": "Invalid Currency Code",
"postgresHasItsOwnCurrencySettings": "PostgreSQL 'money' type has own currency settings",
"validColumnsForBarCode": "The valid Field Types for a Barcode Field are: Number, Single Line Text, Long Text, Phone Number, URL, Email, Decimal. Please create one first.",
"hm": {
"title": "Has Many Relation",
"tooltip_desc": "A single record from table ",
"tooltip_desc2": " can be linked with multiple records from table "
},
"mm": {
"title": "Many to Many Relation",
"tooltip_desc": "Multiple records from table ",
"tooltip_desc2": " can be linked with multiple records from table "
},
"bt": {
"title": "Belongs to Relation",
"tooltip_desc": "A single record from table ",
"tooltip_desc2": " can be linked with a record from table "
},
"oo": {
"title": "One to One Relation",
"tooltip_desc": "A single record from table ",
"tooltip_desc2": " can be linked with a single record from table "
},
"noRecordsAreLinkedFromTable": "No records are linked from table",
"noRecordsLinked": "No records linked",
"recordsLinked": "records linked",
"acceptOnlyValid": "Accepts only",
"apiTokenCreate": "Create personal API tokens to use in automation or external apps.",
"selectFieldToSort": "Select Field to Sort",
"thereAreNoRecordsInTable": "There are no records in table",
"createWebhookMsg1": "Get started with web-hooks!",
"createWebhookMsg2": "Create web-hooks to power you automations,",
"createWebhookMsg3": "Get notified as soon as there are changes in your data",
"areYouSureUWantTo": "Are you sure you want to delete the following",
"areYouSureUWantToDeleteLabel": "Are you sure you want to {deleteLabel} the following",
"idColumnRequired": "ID field is required, you can rename this later if required.",
"length59Required": "The length exceeds the max 59 characters",
"noNewNotifications": "You have no new notifications",
"noRecordFound": "Record not found",
"rowDeleted": "Record deleted",
"saveChanges": "Do you want to save the changes?",
"tooLargeFieldEntity": "The field is too large to be converted to {entity}",
"roleRequired": "Role required",
"warning": {
"dbValid": "Please make sure database you are trying to connect is valid! This operation can cause schema loss!!",
"barcode": {
"renderError": "Barcode error - please check compatibility between input and barcode type"
},
"nonEditableFields": {
"computedFieldUnableToClear": "Warning: Computed field - unable to clear text",
"qrFieldsCannotBeDirectlyChanged": "Warning: QR fields cannot be directly changed."
}
"qrFieldsCannotBeDirectlyChanged": "Warning: QR fields cannot be directly changed.",
"barcodeFieldsCannotBeDirectlyChanged": "Warning: Barcode fields cannot be directly changed."
},
"duplicateProject": "Are you sure you want to duplicate the base?",
"duplicateTable": "Are you sure you want to duplicate the table?"
},
"info": {
"disabledAsViewLocked": "Disabled as View is locked",
"basesMigrated": "Bases are migrated. Please try again.",
"pasteNotSupported": "Paste operation is not supported on the active cell",
"roles": {
"orgCreator": "Creator can create new projects and access any invited project.",
@ -640,6 +1153,9 @@
"tablesMetadataInSync": "টির মিক কর আছ",
"addMultipleUsers": "आप एकिक COMMA (,) द अलग ईमल जड़ सकत",
"enterTableName": "টির নম লিন",
"enterLayoutName": "Enter Layout name",
"enterDashboardName": "Enter Dashboard name",
"defaultColumns": "Default fields",
"addDefaultColumns": "ডিফলট কলম যগ করন",
"tableNameInDb": "ডরকিত টির নম",
"airtable": {
@ -662,8 +1178,10 @@
"valueAlreadyInList": "This value is already in the list",
"noColumnsToUpdate": "No columns to update",
"tableDeleted": "Deleted table successfully",
"layoutDeleted": "Deleted layout successfully",
"generatePublicShareableReadonlyBase": "Generate publicly shareable readonly base",
"deleteViewConfirmation": "Are you sure you want to delete this view?",
"deleteLayoutConfirmation": "Are you sure you want to delete this Layout?",
"deleteTableConfirmation": "Do you want to delete the table",
"showM2mTables": "Show M2M Tables",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
@ -674,18 +1192,40 @@
"deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",
"noMoreRecords": "No more records"
"noMoreRecords": "No more records",
"tokenNameNotEmpty": "Token name should not be empty",
"tokenNameMaxLength": "Token name should not be more than 255 characters",
"dbNameRequired": "Database name is required",
"wsNameRequired": "Workspace name required",
"wsNameMinLength": "Workspace name must be at least 3 characters long",
"wsNameMaxLength": "Workspace name must be at most 50 characters long",
"wsDeleteDlg": "Delete this workspace and all it’s contents.",
"userConfirmation": "I understand that this action is irreversible",
"pageNotFound": "Page Not Found",
"makeLineBreak": "to make a line break",
"goToPrevious": "Go to previous",
"goToNext": "Go to next",
"thankYou": "Thank you!",
"submittedFormData": "You have successfully submitted the form data."
},
"error": {
"nameRequired": "Name Required",
"nameMinLength": "Name must be at least 2 characters long",
"nameMaxLength": "Name must be at most 60 characters long",
"viewNameRequired": "View name is required",
"nameMaxLength256": "Name must be at most 256 characters long",
"viewNameUnique": "View name should be unique",
"searchProject": "আপনর অনসনন {search} এর জনয কনও ফলফল পওযি",
"invalidChar": "ফর পথ অবধ চরির।",
"invalidDbCredentials": "অবধ ডস শপতরগি।",
"unableToConnectToDb": "ডর সগ করত অকষম, অনরহ কর পর করন আপনর ডস আপ আছ।",
"invalidYear": "Invalid year",
"userDoesntHaveSufficientPermission": "বযবহরকর অসিব নই বিি করর জনয পরত অনমতিই।",
"dbConnectionStatus": "অবধ ডস পরিি",
"dbConnectionFailed": "সগ বিিন:",
"nullFilterExists": "Null filter exists. Please remove them",
"signUpRules": {
"emailReqd": "ই-মইল পরযজন",
"emailRequired": "Email is required",
"emailInvalid": "ইমল বধ হত হব",
"passwdRequired": "পসওযড পরযজন",
"passwdLength": "আপনর পসওযড অবশযই কমপক 8 টি অকষর হত হব",
@ -695,7 +1235,9 @@
"atLeastOneUppercase": "One Uppercase letter",
"atLeastOneNumber": "One Number",
"atLeastOneSpecialChar": "One special character",
"allowedSpecialCharList": "Allowed special character list"
"allowedSpecialCharList": "Allowed special character list",
"invalidEmails": "Invalid emails",
"invalidEmail": "Invalid Email"
},
"invalidURL": "Invalid URL",
"invalidEmail": "Invalid Email",
@ -726,6 +1268,8 @@
"nameShouldStartWithAnAlphabetOr_": "Name should start with an alphabet or _",
"followingCharactersAreNotAllowed": "Following characters are not allowed",
"columnNameRequired": "Column name is required",
"duplicateColumnName": "Duplicate field name",
"uiDataTypeRequired": "UI data type is required",
"columnNameExceedsCharacters": "The length of column name exceeds the max {value} characters",
"projectNameExceeds50Characters": "Project name exceeds 50 characters",
"projectNameCannotStartWithSpace": "Project name cannot start with space",
@ -758,6 +1302,7 @@
"futureRelease": "শরই আসছ!"
},
"success": {
"licenseKeyUpdated": "License Key Updated",
"columnDuplicated": "Column duplicated successfully",
"rowDuplicatedWithoutSavedYet": "Row duplicated (not saved)",
"updatedUIACL": "Updated UI ACL for tables successfully",
@ -765,6 +1310,7 @@
"pluginSettingsSaved": "Plugin settings saved successfully",
"pluginTested": "Successfully tested plugin settings",
"tableRenamed": "Table renamed successfully",
"layoutRenamed": "Layout renamed successfully",
"viewDeleted": "View deleted successfully",
"primaryColumnUpdated": "Successfully updated as primary column",
"tableDataExported": "Successfully exported all table data",

628
packages/nc-gui/lang/cs.json

@ -1,5 +1,45 @@
{
"dashboards": {
"create_new_dashboard_project": "Create New Interface",
"connect_data_sources": "Připojit zdroje dat",
"alert": "Alert",
"alert-message": "No databases have been connected. Connect database bases to build interfaces. Skip this step and add databases from the base home page later.",
"select_database_projects_that_you_want_to_link_to_this_dashboard_projects": "Select Database Bases that you want to link to this Interface.",
"create_interface": "Create interface",
"project_name": "Název projektu",
"connect": "Connect",
"buttonActionTypes": {
"open_external_url": "Open external link",
"delete_record": "Delete record",
"update_record": "Update record",
"open_layout": "Open layout"
},
"widgets": {
"static_text": "Text",
"chart": "Chart",
"table": "Table",
"image": "Image",
"map": "Map",
"button": "Button",
"number": "Number",
"bar_chart": "Bar Chart",
"line_chart": "Line Chart",
"area_chart": "Area Chart",
"pie_chart": "Pie Chart",
"donut_chart": "Donut Chart",
"scatter_plot": "Scatter Plot",
"bubble_chart": "Bubble Chart",
"radar_chart": "Radar Chart",
"polar_area_chart": "Polar Area Chart",
"radial_bar_chart": "Radial Bar Chart",
"heatmap_chart": "Heatmap Chart",
"treemap_chart": "Treemap Chart",
"box_plot_chart": "Box Plot Chart",
"candlestick_chart": "Candlestick Chart"
}
},
"general": {
"quit": "Quit",
"home": "Domů",
"load": "Načíst",
"open": "Otevřít",
@ -7,27 +47,67 @@
"yes": "Ano",
"no": "Ne",
"ok": "OK",
"back": "Back",
"and": "a",
"or": "nebo",
"add": "Přidat",
"edit": "Upravit",
"link": "Link",
"links": "Links",
"remove": "Odstranit",
"import": "Import",
"logout": "Log Out",
"empty": "Empty",
"changeIcon": "Change Icon",
"save": "Uložit",
"available": "Available",
"abort": "Abort",
"saving": "Saving",
"cancel": "Zrušit",
"null": "Null",
"escape": "Escape",
"hex": "Hex",
"clear": "Vyprázdnit",
"slack": "Slack",
"comment": "Komentář",
"microsoftTeams": "Microsoft Teams",
"discord": "Discord",
"matterMost": "Mattermost",
"twilio": "Twilio",
"whatsappTwilio": "WhatsApp Twilio",
"quote": "Quote",
"submit": "Potvrdit",
"create": "Vytvořit",
"createEntity": "Vytvořit {entity}",
"creating": "Vytváření",
"creatingEntity": "Vytvářím {entity}",
"details": "Podrobnosti",
"skip": "Skip",
"code": "Code",
"duplicate": "Duplikovat",
"duplicating": "Duplicating",
"activate": "Activate",
"action": "Action",
"insert": "Vložit",
"delete": "Smazat",
"deleteEntity": "Odstranit {entity}",
"bulkInsert": "Bulk Insert",
"bulkDelete": "Bulk Delete",
"bulkUpdate": "Bulk Update",
"deleting": "Deleting",
"update": "Aktualizovat",
"rename": "Přejmenovat",
"reload": "Znovu načíst",
"reset": "Obnovit",
"install": "Instalovat",
"show": "Zobrazit",
"access": "Access",
"visibility": "Viditelnost",
"hide": "Skrýt",
"deprecated": "Deprecated",
"showAll": "Zobrazit vše",
"hideAll": "Skrýt vše",
"notFound": "Not found",
"showMore": "Zobrazit více",
"showOptions": "Zobrazit možnosti",
"hideOptions": "Skrýt možnosti",
@ -39,7 +119,7 @@
"signIn": "PŘIHLÁSIT SE",
"signOut": "Odhlásit se",
"required": "Vyžadováno",
"enableScanner": "Enable Scanner for filling",
"enableScanner": "Povolit skener pro vyplnění",
"preferred": "Preferováno",
"mandatory": "Povinné",
"loading": "Načítání ...",
@ -47,6 +127,8 @@
"upload": "Nahrát",
"download": "Stáhnout",
"default": "Výchozí",
"base": "Source",
"datasource": "Data Source",
"more": "Více",
"less": "Méně",
"event": "Událost",
@ -54,12 +136,14 @@
"after": "Po",
"before": "Před",
"search": "Hledat",
"searchIn": "Hledat v",
"notification": "Oznámení",
"reference": "Odkaz",
"function": "Funkce",
"confirm": "Potvrdit",
"generate": "Generovat",
"copy": "Kopírovat",
"are": "are",
"misc": "Ostatní",
"lock": "Uzamknout",
"unlock": "Odemknout",
@ -76,9 +160,39 @@
"hideField": "Skrýt pole",
"sortAsc": "Seřadit vzestupně",
"sortDesc": "Seřadit sestupně",
"geoDataField": "GeoData Field"
"move": "Move",
"geoDataField": "Pole geodat",
"type": "Typ",
"name": "Název",
"changes": "Changes",
"new": "New",
"old": "Old",
"data": "Data",
"source": "Source",
"destination": "Destination",
"active": "Active",
"inactive": "Inactive",
"linked": "linked",
"finish": "Finish",
"min": "Min",
"max": "Max",
"avg": "Avg",
"sum": "Sum",
"count": "Count",
"countDistinct": "Count Distinct",
"sumDistinct": "Sum Distinct",
"avgDistinct": "Avg Distinct",
"join": "Join",
"options": "Options",
"primaryValue": "Primary Value",
"useSurveyMode": "Use Survey Mode",
"shift": "Shift",
"enter": "Enter",
"seconds": "Seconds"
},
"objects": {
"workspace": "Workspace",
"workspaces": "Workspaces",
"project": "Projekt",
"projects": "Projekty",
"table": "Tabulka",
@ -95,6 +209,7 @@
"webhooks": "Webhooky",
"view": "Pohled",
"views": "Pohledy",
"sidebar": "Sidebar",
"viewType": {
"grid": "Mřížka",
"gallery": "Galerie",
@ -107,16 +222,27 @@
"users": "Uživatelé",
"role": "Role",
"roles": "Role",
"developer": "Developer",
"roleType": {
"owner": "Vlastník",
"creator": "Autor",
"editor": "Editor",
"commenter": "Komentátor",
"viewer": "Sledující",
"noaccess": "No Access",
"superAdmin": "Hlavní administrátor",
"orgLevelCreator": "Tvůrce na úrovni organizace",
"orgLevelViewer": "Prohlížeč na úrovni organizace"
},
"sqlVIew": "SQL pohled"
"sqlVIew": "SQL pohled",
"rowHeight": "Výška řádku",
"heightClass": {
"short": "Krátký",
"medium": "Střední",
"tall": "Vyšší",
"extra": "Nejvyšší"
},
"externalDb": "Externí databáze"
},
"datatype": {
"ID": "ID",
@ -139,7 +265,7 @@
"Currency": "Měna",
"Percent": "Procenta",
"Duration": "Doba trvání",
"GeoData": "GeoData",
"GeoData": "Geodata",
"Rating": "Hodnocení",
"Formula": "Vzorec",
"Rollup": "Rollup",
@ -171,17 +297,63 @@
"isNotNull": "není null"
},
"title": {
"docs": "Dokumentace",
"forum": "Fórum",
"parameter": "Parameter",
"headers": "Headers",
"parameterName": "Parameter Name",
"currencyLocale": "Currency Locale",
"currencyCode": "Kód měny",
"searchMembers": "Vyhledávání členů",
"noMembersFound": "Nenalezeni žádní členové",
"dateJoined": "Date Joined",
"tokenName": "Token name",
"inDesktop": "in Desktop",
"rowData": "Record data",
"creator": "Creator",
"qrCode": "QR Code",
"termsOfService": "Terms of Service",
"updateSelectedRows": "Update Selected Records",
"noFiltersAdded": "Nepřidány žádné filtry",
"editCards": "Edit Cards",
"noFieldsFound": "No fields found",
"displayValue": "Display Value",
"expand": "Expand",
"hideAll": "Hide all",
"hideSystemFields": "Hide system fields",
"removeFile": "Remove File",
"hasMany": "Has Many",
"manyToMany": "Many to Many",
"virtualRelation": "Virtual Relation",
"linkMore": "Link More",
"linkMoreRecords": "Link more records",
"downloadFile": "Stáhnout soubor",
"renameTable": "Rename Table",
"renamingTable": "Renaming Table",
"renamingWs": "Renaming Workspace",
"renameWs": "Rename Workspace",
"deleteWs": "Delete Workspace",
"deletingWs": "Deleting Workspace",
"copyAuthToken": "Copy Auth Token",
"copiedAuthToken": "Copied Auth Token",
"copyInviteToken": "Copy Invite Token",
"showSidebar": "Show Sidebar",
"hideSidebar": "Hide Sidebar",
"creatingTable": "Creating Table",
"erdView": "Zobrazení ERD",
"newBase": "New Data Source",
"newProj": "Nový projekt",
"createBase": "Vytvořit projekt",
"myProject": "Moje projekty",
"formTitle": "Název formuláře",
"collabView": "Společný pohled",
"lockedView": "Uzamčené zobrazení",
"personalView": "Osobní pohled",
"collaborative": "Collaborative",
"locked": "Locked",
"personal": "Personal",
"appStore": "App Store",
"teamAndAuth": "Tým a oprávnění",
"rolesUserMgmt": "Správa rolí a uživatelů",
"userMgmt": "Správa uživatelů",
"apiTokens": "API Tokens",
"apiTokenMgmt": "Správa tokenů API",
"rolesMgmt": "Správa rolí",
"projMeta": "Metadata projektu",
@ -199,25 +371,134 @@
"headLogin": "Přihlásit se | NocoDB",
"resetPassword": "Obnovit heslo",
"teamAndSettings": "Tým a nastavení",
"apiDocs": "Dokumenty API",
"apiDocs": "Dokumentace API",
"importFromAirtable": "Import z tabulky Airtable",
"generateToken": "Generovat token",
"APIsAndSupport": "Rozhraní API a podpora",
"APIsAndSupport": "API a podpora",
"helpCenter": "Centrum nápovědy",
"swaggerDocumentation": "Dokumentace Swagger",
"noLabels": "No Labels",
"swaggerDocumentation": "Swagger dokumentace",
"quickImportFrom": "Rychlý import z",
"quickImport": "Rychlý import",
"quickImportAirtable": "Quick Import - Airtable",
"quickImportCSV": "Quick Import - CSV",
"quickImportExcel": "Quick Import - Excel",
"quickImportJSON": "Quick Import - JSON",
"jsonEditor": "JSON Editor",
"comingSoon": "Coming Soon",
"advancedSettings": "Pokročilá nastavení",
"codeSnippet": "Úryvek kódu",
"keyboardShortcut": "Klávesové zkratky",
"generateRandomName": "Vytvořit náhodné jméno",
"findRowByScanningCode": "Find row by scanning a QR or Barcode"
"findRowByScanningCode": "Find row by scanning a QR or Barcode",
"tokenManagement": "Token Management",
"addNewToken": "Add new token",
"accountSettings": "Nastavení účtu",
"resetPasswordMenu": "Reset Password",
"tokens": "Tokens",
"userManagement": "User Management",
"accountManagement": "Account management",
"licence": "Licence",
"allowAllMimeTypes": "Allow All Mime Types",
"defaultView": "Základní pohled",
"relations": "Relace",
"switchLanguage": "Switch Language",
"renameFile": "Rename File",
"links": {
"noAction": "No Action",
"cascade": "Cascade",
"restrict": "Restrict",
"setNull": "Set NULL",
"setDefault": "Set Default"
}
},
"labels": {
"heading1": "Heading 1",
"heading2": "Heading 2",
"heading3": "Heading 3",
"bold": "Bold",
"italic": "Italic",
"underline": "Underline",
"strike": "Strike",
"taskList": "Task List",
"bulletList": "Bullet List",
"numberedList": "Numbered List",
"downloadData": "Stáhnout data",
"blockQuote": "Block Quote",
"noToken": "No Token",
"tokenLimit": "Only one token per user is allowed",
"duplicateAttachment": "File with name {filename} already attached",
"viewIdColon": "ID Pohledu: {viewId}",
"toAddress": "To Address",
"subject": "Subject",
"body": "Body",
"commaSeparatedMobileNumber": "Comma separated Mobile #",
"headerName": "Header Name",
"icon": "Icon",
"max": "Max",
"enableRichText": "Enable Rich Text",
"idColon": "Id:",
"copiedRecordURL": "Copied Record URL",
"copyRecordURL": "Kopírovat URL záznamu",
"duplicateRecord": "Duplicate record",
"binaryEncodingFormat": "Binary encoding format",
"syntax": "Syntax",
"examples": "Examples",
"durationInfo": "A duration of time in minutes or seconds (e.g. 1:23).",
"addHeader": "Add Header",
"enterDefaultUrlOptional": "Zadejte výchozí URL (volitelné)",
"negative": "Negative",
"discard": "Discard",
"default": "Default",
"defaultNumberPercent": "Default Number (%)",
"durationFormat": "Duration Format",
"dateFormat": "Date Format",
"timeFormat": "Time Format",
"singularLabel": "Singular Label",
"pluralLabel": "Plural Label",
"optional": "(nepovinné)",
"clickToMake": "Click to make",
"visibleForRole": "visible for role:",
"inUI": "in UI Dashboard",
"projectSettings": "Base Settings",
"clickToHide": "Click to hide",
"clickToDownload": "Click to download",
"forRole": "for role",
"clickToCopyViewID": "Kliknutím zkopírujete ID pohledu",
"viewMode": "Režim zobrazení",
"searchUsers": "Search Users",
"superAdmin": "Super Admin",
"allTables": "All Tables",
"members": "Členové",
"dataSources": "Data Sources",
"connectDataSource": "Connect a Data Source",
"searchProjects": "Search Bases",
"createdBy": "Vytvořil/a",
"viewingAttachmentsOf": "Viewing Attachments of",
"readOnly": "Readonly",
"dropHere": "Drop here",
"createdOn": "Created On",
"notifyVia": "Upozornit pomocí",
"projName": "Název projektu",
"profile": "Profile",
"accountDetails": "Account Details",
"controlAppearance": "Control your Appearance.",
"accountEmailID": "Account Email ID",
"backToWorkspace": "Zpět na přehled projektů",
"untitledToken": "Untitled token",
"tableName": "Název tabulky",
"dashboardName": "Dashboard name",
"createView": "Vytvořit pohled",
"creatingView": "Creating View",
"duplicateView": "Duplikovat pohled",
"duplicateGridView": "Duplicate Grid View",
"createGridView": "Create Grid View",
"duplicateGalleryView": "Duplicate Gallery View",
"createGalleryView": "Create Gallery View",
"duplicateFormView": "Duplicate Form View",
"createFormView": "Create Form View",
"duplicateKanbanView": "Duplicate Kanban View",
"createKanbanView": "Create Kanban View",
"viewName": "Název zobrazení",
"viewLink": "Zobrazit odkaz",
"columnName": "Název sloupce",
@ -238,7 +519,7 @@
"action": "Akce",
"actions": "Akce",
"operation": "Operace",
"operationSub": "Sub Operation",
"operationSub": "Dílčí operace",
"operationType": "Typ operace",
"operationSubType": "Podtyp operace",
"description": "Popis",
@ -247,6 +528,14 @@
"where": "Kde",
"cache": "Mezipaměť",
"chat": "Chat",
"showOrHide": "Show or Hide",
"airtable": "Airtable",
"csv": "CSV",
"csvFile": "CSV File",
"json": "JSON",
"jsonFile": "JSON File",
"excel": "Excel",
"microsoftExcel": "Microsoft Excel",
"email": "E-mail",
"storage": "Úložiště",
"uiAcl": "UI-ACL",
@ -255,6 +544,7 @@
"created": "Vytvořeno",
"sqlOutput": "Výstup SQL",
"addOption": "Přidat možnost",
"interfaceColor": "Interface Color",
"qrCodeValueColumn": "Sloupec s hodnotou QR kódu",
"barcodeValueColumn": "Sloupec s hodnotou čárového kódu",
"barcodeFormat": "Formát čárového kódu",
@ -275,20 +565,24 @@
"columnName": "Inflection - Název sloupce"
},
"community": {
"starUs1": "Hvězda",
"starUs1": "Hvězdičkujte",
"starUs2": "nás na Githubu",
"bookDemo": "Zarezervujte si DEMO zdarma",
"getAnswered": "Získejte odpovědi na své otázky",
"joinDiscord": "Připojte se na Discord",
"joinCommunity": "Připojte se k NocoDB komunitě",
"joinReddit": "Připojte se k /r/NocoDB",
"followNocodb": "Sledovat NocoDB"
"followNocodb": "Sledovat NocoDB",
"communityTranslated": "(Community Translated)"
},
"twitter": "Twitter",
"docReference": "Odkaz na dokument",
"selectUserRole": "Vybrat uživatelskou roli",
"childTable": "Podřízená tabulka",
"childColumn": "Podřízený sloupec",
"childField": "Child field",
"linkToAnotherRecord": "Odkaz na jiný záznam",
"links": "Links",
"onUpdate": "Při aktualizaci",
"onDelete": "Při odstranění",
"account": "Účet",
@ -298,16 +592,21 @@
"customTheme": "Vlastní motiv",
"requestDataSource": "Požadujete zdroj dat, který potřebujete?",
"apiKey": "API klíč",
"sharedBase": "Sdílená základna",
"personalAccessToken": "Personal Access Token",
"sharedBaseUrl": "Sdílet URL projektu",
"importData": "Importovat data",
"importSecondaryViews": "Import sekundárních zobrazení",
"importRollupColumns": "Import sloupců rollupu",
"importLookupColumns": "Import sloupců vyhledávání",
"importAttachmentColumns": "Import sloupců příloh",
"importFormulaColumns": "Import sloupců vzorců",
"importUsers": "Import Users (by email)",
"noData": "Žádná data",
"goToDashboard": "Přejít na přehled",
"importing": "Importování",
"formatJson": "Format JSON",
"autoSelectFieldTypes": "Auto-Select Field Types",
"firstRowAsHeaders": "Use First Record as Headers",
"flattenNested": "Zploštění vnořených",
"downloadAllowed": "Stažení povoleno",
"weAreHiring": "Přijímáme nové zaměstnance!",
@ -319,15 +618,67 @@
"commentsOnly": "Pouze komentáře",
"documentation": "Dokumentace",
"subscribeNewsletter": "Přihlaste se k odběru našeho týdenního zpravodaje",
"signUpWithGoogle": "Zaregistrujte se ve službě Google",
"signInWithGoogle": "Přihlášení pomocí služby Google",
"signUpWithProvider": "Sign up with {provider}",
"signInWithProvider": "Sign in with {provider}",
"agreeToTos": "Registrací souhlasíte s podmínkami služby.",
"welcomeToNc": "Vítejte na NocoDB!",
"inviteOnlySignup": "Povolit registraci pouze pomocí pozvánky s odkazem",
"nextRow": "Další řádek",
"prevRow": "Předchozí řada"
"prevRow": "Předchozí řada",
"addRowGrid": "Manually add data in grid view",
"addRowForm": "Enter record data through a form",
"noAccess": "No access",
"restApis": "Rest APIs",
"apis": "APIs",
"includeData": "Include Data",
"includeView": "Include View",
"includeWebhook": "Include Webhook",
"zoomInToViewColumns": "Zoom in to view columns",
"embedInSite": "Embed this view in your site",
"titleRequired": "title is required.",
"sourceNameRequired": "Source name is required",
"changeWsName": "Change Workspace Name",
"pressEnter": "Press Enter",
"newFormLoaded": "New form will be loaded after"
},
"activity": {
"openInANewTab": "Open in a new tab",
"copyIFrameCode": "Copy IFrame code",
"onCondition": "On Condition",
"bulkDownload": "Bulk Download",
"attachFile": "Attach File",
"viewAttachment": "View Attachments",
"attachmentDrop": "Click or drop a file into cell",
"addFiles": "Add File(s)",
"hideInUI": "Hide in UI",
"addBase": "Add Base",
"addParameter": "Add Parameter",
"submitAnotherForm": "Submit Another Form",
"dragAndDropFieldsHereToAdd": "Drag and drop fields here to add",
"editSource": "Edit Data Source",
"enterText": "Enter text",
"okEditBase": "Ok & Edit Base",
"showInUI": "Show in UI",
"outOfSync": "Out of sync",
"newSource": "New Data Source",
"newWebhook": "New Webhook",
"enablePublicAccess": "Povolit veřejný přístup",
"doYouWantToSaveTheChanges": "Do you want to save the changes ?",
"editingAccess": "Editing access",
"enabledPublicViewing": "Enable public viewing",
"restrictAccessWithPassword": "Restrict access with password",
"manageProjectAccess": "Správa přístupu k projektu",
"allowDownload": "Allow Download",
"surveyMode": "Survey Mode",
"rtlOrientation": "RTL Orientation",
"useTheme": "Use Theme",
"copyLink": "Copy Link",
"copiedLink": "Link Copied",
"copyInviteLink": "Copy invite link",
"copiedInviteLink": "Copied invite link",
"copyUrl": "Kopírovat URL adresu",
"moreColors": "More Colors",
"moveProject": "Move Base",
"createProject": "Vytvořit projekt",
"importProject": "Import projektu",
"searchProject": "Vyhledat projekt",
@ -338,6 +689,7 @@
"deleteProject": "Smazat projekt",
"refreshProject": "Aktualizovat projekty",
"saveProject": "Uložit projekt",
"saveAndQuit": "Save & Quit",
"deleteKanbanStack": "Smazat zásobník?",
"createProjectExtended": {
"extDB": "Vytvořit připojením <br>k externí databázi",
@ -353,6 +705,7 @@
"translate": "Pomozte s překladem",
"account": {
"authToken": "Kopírovat ověřovací token",
"authTokenCopied": "Copied Auth Token",
"swagger": "Swagger: REST API",
"projInfo": "Kopírovat informace o projektu",
"themes": "Motivy"
@ -362,7 +715,10 @@
"filter": "Filtr",
"addFilter": "Přidat filtr",
"share": "Sdílet",
"groupBy": "Seskupit dle",
"addSubGroup": "Add subgroup",
"shareBase": {
"label": "Sdílet projekt",
"disable": "Zakázat sdílenou základnu",
"enable": "Kdokoli s odkazem",
"link": "Sdílený základní odkaz"
@ -372,6 +728,8 @@
"inviteTeam": "Pozvat tým",
"inviteUser": "Pozvat uživatele",
"inviteToken": "Pozvánkový žeton",
"linkedRecords": "Linked Records",
"addNewLink": "Add New Link",
"newUser": "Nový uživatel",
"editUser": "Upravit uživatele",
"deleteUser": "Odstranění uživatele z projektu",
@ -386,11 +744,14 @@
"previousRecord": "Předchozí rekord",
"copyApiURL": "Kopírování adresy URL rozhraní API",
"createTable": "Create New Table",
"createDashboard": "Create Dashboard",
"createWorkspace": "Create Workspace",
"refreshTable": "Tabulky Obnovení",
"renameTable": "Rename Table",
"deleteTable": "Delete Table",
"renameTable": "Přejmenovat tabulku",
"renameLayout": "Layout Rename",
"deleteTable": "Smazat tabulku",
"addField": "Přidání nového pole do této tabulky",
"setDisplay": "Set as Display value",
"setDisplay": "Nastav jako zobrazovanou hodnotu",
"addRow": "Přidat nový řádek",
"saveRow": "Uložit řádek",
"saveAndExit": "Uložit a odejít",
@ -398,6 +759,9 @@
"insertRow": "Vložit nový řádek",
"duplicateRow": "Duplikovat řádek",
"deleteRow": "Odstranit řádek",
"deleteRows": "Delete records",
"predictColumns": "Predict Fields",
"predictFormulas": "Predict Formulas",
"deleteSelectedRow": "Odstranit vybrané řádky",
"importExcel": "Importovat Excel",
"importCSV": "Importovat CSV",
@ -413,11 +777,12 @@
"createView": "Vytvořit pohled",
"shareView": "Sdílet pohled",
"findRowByCodeScan": "Find row by scan",
"fillByCodeScan": "Fill by scan",
"fillByCodeScan": "Vyplnit skenováním",
"listSharedView": "Seznam sdílených zobrazení",
"ListView": "Seznam pohledů",
"copyView": "Kopírovat pohled",
"renameView": "Přejmenovat pohled",
"uploadData": "Nahrát data",
"deleteView": "Odstranit pohled",
"createGrid": "Vytvoření zobrazení mřížky",
"createGallery": "Vytvořit zobrazení galerie",
@ -425,7 +790,6 @@
"createKanban": "Vytvoření zobrazení Kanban",
"createForm": "Vytvořit zobrazení formuláře",
"showSystemFields": "Zobrazit systémová pole",
"copyUrl": "Kopírovat URL adresu",
"openTab": "Otevřít novou kartu",
"iFrame": "Kopírování vložitelného kódu HTML",
"addWebhook": "Přidat nový webhook",
@ -451,10 +815,24 @@
"addFilterGroup": "Přidání skupiny filtrů",
"linkRecord": "Odkaz na záznam",
"addNewRecord": "Přidání nového záznamu",
"newRecord": "New record",
"tableNameCreateNewRecord": "{tableName}: Create new record",
"gotSavedLinkedSuccessfully": "{tableName} '{recordTitle}' got saved & linked successfully",
"recordCreatedLinked": "Record Created & Linked",
"useConnectionUrl": "Použít adresu URL připojení",
"toggleCommentsDraw": "Přepínání komentářů draw",
"expandRecord": "Rozbalit záznam",
"deleteRecord": "Odstranění záznamu",
"fullWidth": "Full width",
"exitFullWidth": "Exit full width",
"markAllAsRead": "Mark all as read",
"column": {
"delete": "Delete Field",
"addNumber": "Add Number Field",
"addSingleLineText": "Add SingleLineText Field",
"addLongText": "Add LongText Field",
"addOther": "Add Other Field"
},
"erd": {
"showColumns": "Zobrazit sloupce",
"showPkAndFk": "Zobrazit primární a cizí klíče",
@ -470,14 +848,16 @@
"addOrEditStack": "Přidat / upravit zásobník"
},
"map": {
"mappedBy": "Mapped By",
"chooseMappingField": "Choose a Mapping Field",
"mappedBy": "Umístěno podle",
"chooseMappingField": "Vyberte pole s umístěním",
"openInGoogleMaps": "Google mapy",
"openInOpenStreetMap": "OSM"
},
"toggleMobileMode": "Toggle Mobile Mode"
"toggleMobileMode": "Přepnout Mobilní režim",
"startCommenting": "Start commenting!"
},
"tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment",
"saveChanges": "Uložení změn",
"xcDB": "Vytvoření nového projektu",
"extDB": "Podpora MySQL, PostgreSQL, SQL Server a SQLite",
@ -488,6 +868,7 @@
"light": "Dodává se v černé barvě ? (^⇧B)"
},
"addTable": "Přidání nové tabulky",
"addDashboard": "Add new Dashboard",
"inviteMore": "Pozvat další uživatele",
"toggleNavDraw": "Přepnout navigační zásuvku",
"reloadApiToken": "Načtení tokenů API",
@ -506,7 +887,19 @@
"clientCA": "Vyberte soubor CA"
},
"placeholder": {
"selectSlackChannels": "Select Slack channels",
"selectTeamsChannels": "Select Microsoft Teams channels",
"selectDiscordChannels": "Select Discord channels",
"selectMattermostChannels": "Select Mattermost channels",
"webhookTitle": "Webhook Title",
"barcodeColumn": "Select a field for the Barcode value",
"notFoundContent": "No valid field Type can be found.",
"selectBarcodeFormat": "Select a Barcode format",
"projName": "Zadejte název projektu",
"selectGroupField": "Select a Grouping Field",
"selectGroupFieldNotFound": "No Single Select Field can be found. Please create one first.",
"selectGeoField": "Select a GeoData Field",
"selectGeoFieldNotFound": "No GeoData Field can be found. Please create one first.",
"password": {
"enter": "Zadejte heslo",
"current": "Aktuální heslo",
@ -514,6 +907,8 @@
"save": "Uložit heslo",
"confirm": "Potvrzení nového hesla"
},
"selectAColumnForTheQRCodeValue": "Select a field for the QR code value",
"allowNegativeNumbers": "Allow negative numbers",
"searchProjectTree": "Vyhledávací tabulky",
"searchFields": "Vyhledávací pole",
"searchColumn": "Sloupec Hledat {search}",
@ -523,34 +918,152 @@
"defaultValue": "Výchozí hodnota",
"filterByEmail": "Filtrování podle e-mailu",
"filterQuery": "Filtrování dotazu",
"selectField": "Vyberte pole"
"selectField": "Vyberte pole",
"precision": "Precision",
"decimal1": "1.0",
"decimal2": "1.00",
"decimal3": "1.000",
"decimal4": "1.0000",
"decimal5": "1.00000",
"decimal6": "1.000000",
"decimal7": "1.0000000",
"decimal8": "1.00000000",
"value": "Value",
"key": "Key"
},
"msg": {
"clickToCopyFieldId": "Click to copy Field Id",
"enterPassword": "Enter password",
"bySigningUp": "By signing up, you agree to the",
"subscribeToOurWeeklyNewsletter": "Subscribe to our weekly newsletter",
"verifyingPassword": "Verifying Password",
"thisSharedViewIsProtected": "This shared view is protected",
"successfullySubmittedFormData": "Successfully submitted form data",
"formViewNotSupportedOnMobile": "Form view is not supported on mobile",
"newFormWillBeLoaded": "New form will be loaded after {seconds} seconds",
"optimizedQueryDisabled": "Optimized query is disabled",
"optimizedQueryEnabled": "Optimized query is enabled",
"lookupNonBtWarning": "Lookup field is not supported for non-Belongs to relation",
"invalidTime": "Invalid Time",
"linkColumnClearNotSupportedYet": "You don't have any supported links for Lookup",
"recordCouldNotBeFound": "Record could not be found",
"invalidPhoneNumber": "Invalid phone number",
"pageSizeChanged": "Page size changed",
"errorLoadingData": "Error loading data",
"webhookBodyMsg1": "Use context variable",
"webhookBodyMsg2": "body",
"webhookBodyMsg3": "to refer the record under consideration",
"formula": {
"hintStart": "Hint: Use {placeholder1} to reference fields, e.g: {placeholder2}. For more, please check out",
"hintEnd": "Formulas.",
"noSuggestedFormulaFound": "No suggested formula found",
"numericTypeIsExpected": "Numeric type is expected",
"stringTypeIsExpected": "String type is expected",
"operationNotAvailable": "{operation} operation not available",
"cantSaveFieldFormulaInvalid": "Can’t save field because formula is invalid",
"notSupportedToReferenceColumn": "Not supported to reference field {columnName}",
"typeIsExpectedButFound": "Type {type} is expected but found Type {found}",
"requiredArgumentsFormula": "{calleeName} requires {requiredArguments} arguments",
"minRequiredArgumentsFormula": "{calleeName} required minimum {minRequiredArguments} arguments",
"maxRequiredArgumentsFormula": "{calleeName} required maximum {maxRequiredArguments} arguments",
"functionNotAvailable": "{function} function is not available",
"firstParamWeekDayHaveDate": "The first parameter of WEEKDAY() should have date value",
"secondParamWeekDayHaveDate": "The second parameter of WEEKDAY() should have the value either \"sunday\", \"monday\", \"tuesday\", \"wednesday\", \"thursday\", \"friday\" or \"saturday\"",
"firstParamDateAddHaveDate": "The first parameter of DATEADD() should have date value",
"secondParamDateAddHaveNumber": "The second parameter of DATEADD() should have numeric value",
"thirdParamDateAddHaveDate": "The third parameter of DATEADD() should have the value either \"day\", \"week\", \"month\" or \"year\"",
"firstParamDateDiffHaveDate": "The first parameter of DATEDIFF() should have date value",
"secondParamDateDiffHaveDate": "The second parameter of DATEDIFF() should have date value",
"thirdParamDateDiffHaveDate": "The third parameter of DATETIME_DIFF() should have value either \"milliseconds\", \"ms\", \"seconds\", \"s\", \"minutes\", \"m\", \"hours\", \"h\", \"days\", \"d\", \"weeks\", \"w\", \"months\", \"M\", \"quarters\", \"Q\", \"years\", or \"y\"",
"columnNotAvailable": "Field {columnName} is not available",
"cantSaveCircularReference": "Can’t save field because it causes a circular reference",
"columnWithTypeFoundButExpected": "Field {columnName} with {columnType} type is found but {expectedType} type is expected",
"columnNotMatchedWithType": "{columnName} is not matched with {columnType}"
},
"selectOption": {
"cantBeNull": "Select options can't be null",
"multiSelectCantHaveCommas": "MultiSelect fields can't have commas(',')",
"cantHaveDuplicates": "Select options can't have duplicates",
"createNewOptionNamed": "Create new option named"
},
"plsEnterANumber": "Please enter a number",
"plsInputEmail": "Please input email",
"invalidDate": "Invalid date",
"invalidLocale": "Invalid locale",
"invalidCurrencyCode": "Invalid Currency Code",
"postgresHasItsOwnCurrencySettings": "PostgreSQL 'money' type has own currency settings",
"validColumnsForBarCode": "The valid Field Types for a Barcode Field are: Number, Single Line Text, Long Text, Phone Number, URL, Email, Decimal. Please create one first.",
"hm": {
"title": "Has Many Relation",
"tooltip_desc": "A single record from table ",
"tooltip_desc2": " can be linked with multiple records from table "
},
"mm": {
"title": "Many to Many Relation",
"tooltip_desc": "Multiple records from table ",
"tooltip_desc2": " can be linked with multiple records from table "
},
"bt": {
"title": "Belongs to Relation",
"tooltip_desc": "A single record from table ",
"tooltip_desc2": " can be linked with a record from table "
},
"oo": {
"title": "One to One Relation",
"tooltip_desc": "A single record from table ",
"tooltip_desc2": " can be linked with a single record from table "
},
"noRecordsAreLinkedFromTable": "No records are linked from table",
"noRecordsLinked": "No records linked",
"recordsLinked": "records linked",
"acceptOnlyValid": "Accepts only",
"apiTokenCreate": "Create personal API tokens to use in automation or external apps.",
"selectFieldToSort": "Select Field to Sort",
"thereAreNoRecordsInTable": "There are no records in table",
"createWebhookMsg1": "Get started with web-hooks!",
"createWebhookMsg2": "Create web-hooks to power you automations,",
"createWebhookMsg3": "Get notified as soon as there are changes in your data",
"areYouSureUWantTo": "Are you sure you want to delete the following",
"areYouSureUWantToDeleteLabel": "Are you sure you want to {deleteLabel} the following",
"idColumnRequired": "ID field is required, you can rename this later if required.",
"length59Required": "The length exceeds the max 59 characters",
"noNewNotifications": "You have no new notifications",
"noRecordFound": "Record not found",
"rowDeleted": "Record deleted",
"saveChanges": "Do you want to save the changes?",
"tooLargeFieldEntity": "The field is too large to be converted to {entity}",
"roleRequired": "Role required",
"warning": {
"dbValid": "Please make sure database you are trying to connect is valid! This operation can cause schema loss!!",
"barcode": {
"renderError": "Chyba čárového kódu - zkontrolujte prosím kompatibilitu mezi typem vstupního a čárového kódu"
},
"nonEditableFields": {
"computedFieldUnableToClear": "Varování: Vypočítané pole - nelze vymazat text",
"qrFieldsCannotBeDirectlyChanged": "Varování: Pole QR nelze přímo měnit."
}
"qrFieldsCannotBeDirectlyChanged": "Varování: Pole QR nelze přímo měnit.",
"barcodeFieldsCannotBeDirectlyChanged": "Warning: Barcode fields cannot be directly changed."
},
"duplicateProject": "Are you sure you want to duplicate the base?",
"duplicateTable": "Are you sure you want to duplicate the table?"
},
"info": {
"disabledAsViewLocked": "Disabled as View is locked",
"basesMigrated": "Bases are migrated. Please try again.",
"pasteNotSupported": "Operace Vložit není v aktivní buňce podporována.",
"roles": {
"orgCreator": "Tvůrce může vytvářet nové projekty a přistupovat k jakémukoli pozvanému projektu.",
"orgViewer": "Prohlížeč nemůže vytvářet nové projekty, ale může přistupovat k jakémukoli pozvanému projektu."
},
"codeScanner": {
"loadingScanner": "Loading the scanner...",
"loadingScanner": "Načítání skeneru...",
"selectColumn": "Select a column (QR code or Barcode) that you want to use for finding a row by scanning.",
"moreThanOneRowFoundForCode": "More than one row found for this code. Currently only unique codes are supported.",
"noRowFoundForCode": "No row found for this code for the selected column"
},
"map": {
"overLimit": "You're over the limit.",
"closeLimit": "You're getting close to the limit.",
"limitNumber": "The limit of markers shown in a Map View is 1000 records."
"overLimit": "Překročili jste limit.",
"closeLimit": "Blížíte se k limitu.",
"limitNumber": "Limit značek zobrazených na mapě je 1000 záznamů."
},
"footerInfo": "Řádky na stránku",
"upload": "Vyberte soubor, který chcete nahrát",
@ -640,6 +1153,9 @@
"tablesMetadataInSync": "Metadata tabulek jsou synchronizována",
"addMultipleUsers": "Můžete přidat více e-mailů oddělených čárkou(,).",
"enterTableName": "Zadejte název tabulky",
"enterLayoutName": "Enter Layout name",
"enterDashboardName": "Enter Dashboard name",
"defaultColumns": "Default fields",
"addDefaultColumns": "Přidání výchozích sloupců",
"tableNameInDb": "Název tabulky uložený v databázi",
"airtable": {
@ -662,30 +1178,54 @@
"valueAlreadyInList": "Tato hodnota je již v seznamu",
"noColumnsToUpdate": "Žádné sloupce k aktualizaci",
"tableDeleted": "Úspěšně odstraněná tabulka",
"layoutDeleted": "Deleted layout successfully",
"generatePublicShareableReadonlyBase": "Generování veřejně sdílené readonly báze",
"deleteViewConfirmation": "Opravdu chcete toto zobrazení odstranit?",
"deleteLayoutConfirmation": "Are you sure you want to delete this Layout?",
"deleteTableConfirmation": "Chcete odstranit tabulku",
"showM2mTables": "Zobrazit tabulky M2M",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showM2mTablesDesc": "Vztah M:N (více ku více) je podporován prostřednictvím propojovací tabulky a ve výchozím stavu je skrytý. Povolením této možnosti zobrazíte všechny takové tabulky spolu s existujícími tabulkami.",
"showNullInCells": "Zobrazit NULL v buňkách",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"showNullInCellsDesc": "Zobrazte štítek 'NULL' v buňkách obsahujících hodnotu NULL. To pomáhá odlišit je od buněk obsahujících prázdný řetězec (EMPTY string).",
"showNullAndEmptyInFilter": "Zobrazit NULL a EMPTY ve filtru",
"showNullAndEmptyInFilterDesc": "Povolení \"dodatečných\" filtrů pro rozlišení polí obsahujících NULL a prázdné řetězce (EMPTY). Výchozí chování pro prázdná pole zachází s řetězci NULL a EMPTY stejně.",
"deleteKanbanStackConfirmation": "Odstraněním tohoto zásobníku se také odstraní možnost výběru `{stackToBeDeleted}` z `{groupingField}`. Záznamy se přesunou do zásobníku nezařazených záznamů.",
"computedFieldEditWarning": "Vypočtené pole: obsah je určen pouze pro čtení. Ke změně konfigurace sloupce použijte nabídku úprav sloupce",
"computedFieldDeleteWarning": "Vypočtené pole: obsah je určen pouze pro čtení. Nelze vymazat obsah.",
"noMoreRecords": "Žádné další záznamy"
"noMoreRecords": "Žádné další záznamy",
"tokenNameNotEmpty": "Token name should not be empty",
"tokenNameMaxLength": "Token name should not be more than 255 characters",
"dbNameRequired": "Database name is required",
"wsNameRequired": "Workspace name required",
"wsNameMinLength": "Workspace name must be at least 3 characters long",
"wsNameMaxLength": "Workspace name must be at most 50 characters long",
"wsDeleteDlg": "Delete this workspace and all it’s contents.",
"userConfirmation": "I understand that this action is irreversible",
"pageNotFound": "Page Not Found",
"makeLineBreak": "to make a line break",
"goToPrevious": "Go to previous",
"goToNext": "Go to next",
"thankYou": "Thank you!",
"submittedFormData": "You have successfully submitted the form data."
},
"error": {
"nameRequired": "Name Required",
"nameMinLength": "Name must be at least 2 characters long",
"nameMaxLength": "Name must be at most 60 characters long",
"viewNameRequired": "View name is required",
"nameMaxLength256": "Name must be at most 256 characters long",
"viewNameUnique": "View name should be unique",
"searchProject": "Vaše hledání na {search} nenašlo žádné výsledky",
"invalidChar": "Neplatný znak v cestě ke složce.",
"invalidDbCredentials": "Neplatné pověření k databázi.",
"unableToConnectToDb": "Nelze se připojit k databázi, zkontrolujte prosím, zda je databáze funkční.",
"invalidYear": "Invalid year",
"userDoesntHaveSufficientPermission": "Uživatel neexistuje nebo nemá dostatečné oprávnění k vytvoření schématu.",
"dbConnectionStatus": "Neplatné parametry databáze",
"dbConnectionFailed": "Selhání připojení:",
"nullFilterExists": "Null filter exists. Please remove them",
"signUpRules": {
"emailReqd": "Je vyžadován e-mail",
"emailRequired": "Email is required",
"emailInvalid": "E-mail musí být platný",
"passwdRequired": "Heslo je vyžadováno",
"passwdLength": "Heslo musí mít alespoň 8 znaků",
@ -695,7 +1235,9 @@
"atLeastOneUppercase": "Jedno velké písmeno",
"atLeastOneNumber": "Jedno číslo",
"atLeastOneSpecialChar": "Jeden speciální znak",
"allowedSpecialCharList": "Seznam povolených speciálních znaků"
"allowedSpecialCharList": "Seznam povolených speciálních znaků",
"invalidEmails": "Invalid emails",
"invalidEmail": "Invalid Email"
},
"invalidURL": "Neplatná adresa URL",
"invalidEmail": "Neplatný e-mail",
@ -726,6 +1268,8 @@
"nameShouldStartWithAnAlphabetOr_": "Jméno by mělo začínat abecedou nebo _",
"followingCharactersAreNotAllowed": "Následující znaky nejsou povoleny",
"columnNameRequired": "Název sloupce je povinný",
"duplicateColumnName": "Duplicate field name",
"uiDataTypeRequired": "UI data type is required",
"columnNameExceedsCharacters": "The length of column name exceeds the max {value} characters",
"projectNameExceeds50Characters": "Název projektu přesahuje 50 znaků",
"projectNameCannotStartWithSpace": "Název projektu nesmí začínat mezerou",
@ -758,6 +1302,7 @@
"futureRelease": "Již brzy!"
},
"success": {
"licenseKeyUpdated": "License Key Updated",
"columnDuplicated": "Sloupec úspěšně duplikován",
"rowDuplicatedWithoutSavedYet": "Řádek duplikován (neuložen)",
"updatedUIACL": "Úspěšná aktualizace uživatelského rozhraní ACL pro tabulky",
@ -765,6 +1310,7 @@
"pluginSettingsSaved": "Nastavení zásuvného modulu bylo úspěšně uloženo",
"pluginTested": "Úspěšně otestované nastavení zásuvného modulu",
"tableRenamed": "Tabulka byla úspěšně přejmenována",
"layoutRenamed": "Layout renamed successfully",
"viewDeleted": "Zobrazení úspěšně odstraněno",
"primaryColumnUpdated": "Úspěšně aktualizováno jako primární sloupec",
"tableDataExported": "Úspěšný export všech dat tabulky",
@ -779,7 +1325,7 @@
"userDeletedFromProject": "Úspěšné odstranění uživatele z projektu",
"inviteEmailSent": "E-mail s pozvánkou byl úspěšně odeslán",
"inviteURLCopied": "Adresa URL pozvánky zkopírovaná do schránky",
"commentCopied": "Comment copied to clipboard",
"commentCopied": "Komentář zkopírován do schránky",
"passwordResetURLCopied": "Adresa URL pro resetování hesla zkopírovaná do schránky",
"shareableURLCopied": "Zkopírovaná sdílená základní adresa URL do schránky!",
"embeddableHTMLCodeCopied": "Zkopírovaný vložitelný kód HTML!",

604
packages/nc-gui/lang/da.json

@ -1,5 +1,45 @@
{
"dashboards": {
"create_new_dashboard_project": "Create New Interface",
"connect_data_sources": "Connect data sources",
"alert": "Alert",
"alert-message": "No databases have been connected. Connect database bases to build interfaces. Skip this step and add databases from the base home page later.",
"select_database_projects_that_you_want_to_link_to_this_dashboard_projects": "Select Database Bases that you want to link to this Interface.",
"create_interface": "Create interface",
"project_name": "Base Name",
"connect": "Connect",
"buttonActionTypes": {
"open_external_url": "Open external link",
"delete_record": "Delete record",
"update_record": "Update record",
"open_layout": "Open layout"
},
"widgets": {
"static_text": "Text",
"chart": "Chart",
"table": "Table",
"image": "Image",
"map": "Map",
"button": "Button",
"number": "Number",
"bar_chart": "Bar Chart",
"line_chart": "Line Chart",
"area_chart": "Area Chart",
"pie_chart": "Pie Chart",
"donut_chart": "Donut Chart",
"scatter_plot": "Scatter Plot",
"bubble_chart": "Bubble Chart",
"radar_chart": "Radar Chart",
"polar_area_chart": "Polar Area Chart",
"radial_bar_chart": "Radial Bar Chart",
"heatmap_chart": "Heatmap Chart",
"treemap_chart": "Treemap Chart",
"box_plot_chart": "Box Plot Chart",
"candlestick_chart": "Candlestick Chart"
}
},
"general": {
"quit": "Quit",
"home": "Forside",
"load": "Indlæs",
"open": "Åbn",
@ -7,27 +47,67 @@
"yes": "Ja",
"no": "Nej",
"ok": "Okay",
"back": "Back",
"and": "Og",
"or": "Eller",
"add": "Tilføj",
"edit": "Redigér",
"link": "Link",
"links": "Links",
"remove": "Fjern",
"import": "Import",
"logout": "Log Out",
"empty": "Empty",
"changeIcon": "Change Icon",
"save": "Gem",
"available": "Available",
"abort": "Abort",
"saving": "Saving",
"cancel": "Fortryd",
"null": "Null",
"escape": "Escape",
"hex": "Hex",
"clear": "Clear",
"slack": "Slack",
"comment": "Comment",
"microsoftTeams": "Microsoft Teams",
"discord": "Discord",
"matterMost": "Mattermost",
"twilio": "Twilio",
"whatsappTwilio": "WhatsApp Twilio",
"quote": "Quote",
"submit": "Indsend",
"create": "Opret",
"createEntity": "Create {entity}",
"creating": "Creating",
"creatingEntity": "Creating {entity}",
"details": "Details",
"skip": "Skip",
"code": "Code",
"duplicate": "Duplikat",
"duplicating": "Duplicating",
"activate": "Activate",
"action": "Action",
"insert": "Indsæt",
"delete": "Slet",
"deleteEntity": "Delete {entity}",
"bulkInsert": "Bulk Insert",
"bulkDelete": "Bulk Delete",
"bulkUpdate": "Bulk Update",
"deleting": "Deleting",
"update": "Opdatér",
"rename": "Omdøb",
"reload": "Genindlæs",
"reset": "Nulstil",
"install": "Installer",
"show": "Vis",
"access": "Access",
"visibility": "Visibility",
"hide": "Skjul",
"deprecated": "Deprecated",
"showAll": "Vis alt",
"hideAll": "Gem alt",
"notFound": "Not found",
"showMore": "Vis mere",
"showOptions": "Vis muligheder.",
"hideOptions": "Skjul muligheder.",
@ -39,7 +119,7 @@
"signIn": "LOG IND",
"signOut": "Log ud",
"required": "Påkrævet",
"enableScanner": "Enable Scanner for filling",
"enableScanner": "Aktiver scanner til udfyldning",
"preferred": "Foretrukne",
"mandatory": "Obligatorisk",
"loading": "Indlæser ...",
@ -47,6 +127,8 @@
"upload": "Upload",
"download": "Hent",
"default": "Standard",
"base": "Source",
"datasource": "Data Source",
"more": "Mere",
"less": "Mindre",
"event": "Begivenhed",
@ -54,12 +136,14 @@
"after": "Efter",
"before": "Før",
"search": "Søg",
"searchIn": "Search In",
"notification": "Notifikation",
"reference": "Henvisning",
"function": "Fungere",
"confirm": "Bekræft",
"generate": "Generer",
"copy": "Kopier",
"are": "are",
"misc": "Diverse",
"lock": "Lås",
"unlock": "Lås op",
@ -76,9 +160,39 @@
"hideField": "Skjul felt",
"sortAsc": "Sortere stigende",
"sortDesc": "Sortere nedadgående",
"geoDataField": "GeoData-felt"
"move": "Move",
"geoDataField": "GeoData-felt",
"type": "Type",
"name": "Name",
"changes": "Changes",
"new": "New",
"old": "Old",
"data": "Data",
"source": "Source",
"destination": "Destination",
"active": "Active",
"inactive": "Inactive",
"linked": "linked",
"finish": "Finish",
"min": "Min",
"max": "Max",
"avg": "Avg",
"sum": "Sum",
"count": "Count",
"countDistinct": "Count Distinct",
"sumDistinct": "Sum Distinct",
"avgDistinct": "Avg Distinct",
"join": "Join",
"options": "Options",
"primaryValue": "Primary Value",
"useSurveyMode": "Use Survey Mode",
"shift": "Shift",
"enter": "Enter",
"seconds": "Seconds"
},
"objects": {
"workspace": "Workspace",
"workspaces": "Workspaces",
"project": "Projekt",
"projects": "Projekter",
"table": "Bord",
@ -95,6 +209,7 @@
"webhooks": "Webhooks.",
"view": "Visning",
"views": "Visninger",
"sidebar": "Sidebar",
"viewType": {
"grid": "Grid",
"gallery": "Galleri",
@ -107,16 +222,27 @@
"users": "Brugere",
"role": "Rolle",
"roles": "Roller.",
"developer": "Developer",
"roleType": {
"owner": "Ejer",
"creator": "Skaber.",
"editor": "Editor.",
"commenter": "Kommenter.",
"viewer": "Viewer.",
"noaccess": "No Access",
"superAdmin": "Super Admin",
"orgLevelCreator": "Skaberen på organisationsniveau",
"orgLevelViewer": "Visning på organisationsniveau"
},
"sqlVIew": "SQL-visning"
"sqlVIew": "SQL-visning",
"rowHeight": "Record Height",
"heightClass": {
"short": "Short",
"medium": "Medium",
"tall": "Tall",
"extra": "Extra"
},
"externalDb": "External Database"
},
"datatype": {
"ID": "ID.",
@ -171,17 +297,63 @@
"isNotNull": "er ikke null."
},
"title": {
"docs": "Docs",
"forum": "Forum",
"parameter": "Parameter",
"headers": "Headers",
"parameterName": "Parameter Name",
"currencyLocale": "Currency Locale",
"currencyCode": "Currency Code",
"searchMembers": "Search Members",
"noMembersFound": "No members found",
"dateJoined": "Date Joined",
"tokenName": "Token name",
"inDesktop": "in Desktop",
"rowData": "Record data",
"creator": "Creator",
"qrCode": "QR Code",
"termsOfService": "Terms of Service",
"updateSelectedRows": "Update Selected Records",
"noFiltersAdded": "No filters added",
"editCards": "Edit Cards",
"noFieldsFound": "No fields found",
"displayValue": "Display Value",
"expand": "Expand",
"hideAll": "Hide all",
"hideSystemFields": "Hide system fields",
"removeFile": "Remove File",
"hasMany": "Has Many",
"manyToMany": "Many to Many",
"virtualRelation": "Virtual Relation",
"linkMore": "Link More",
"linkMoreRecords": "Link more records",
"downloadFile": "Download File",
"renameTable": "Rename Table",
"renamingTable": "Renaming Table",
"renamingWs": "Renaming Workspace",
"renameWs": "Rename Workspace",
"deleteWs": "Delete Workspace",
"deletingWs": "Deleting Workspace",
"copyAuthToken": "Copy Auth Token",
"copiedAuthToken": "Copied Auth Token",
"copyInviteToken": "Copy Invite Token",
"showSidebar": "Show Sidebar",
"hideSidebar": "Hide Sidebar",
"creatingTable": "Creating Table",
"erdView": "ERD-visning",
"newBase": "New Data Source",
"newProj": "Nyt projekt",
"createBase": "Create Base",
"myProject": "Mine projekter",
"formTitle": "Form titel",
"collabView": "Collaborative View.",
"lockedView": "Låst udsigt",
"personalView": "Personlig visning",
"collaborative": "Collaborative",
"locked": "Locked",
"personal": "Personal",
"appStore": "App butik",
"teamAndAuth": "Team & Auth.",
"rolesUserMgmt": "Roller & Brugere Management",
"userMgmt": "Bruger Management",
"apiTokens": "API Tokens",
"apiTokenMgmt": "API TOKENS MANAGEMENT",
"rolesMgmt": "Roller Management.",
"projMeta": "Projektmetadata.",
@ -204,20 +376,129 @@
"generateToken": "Generer et symbol",
"APIsAndSupport": "API'er og support",
"helpCenter": "Hjælp-center",
"noLabels": "No Labels",
"swaggerDocumentation": "Swagger-dokumentation",
"quickImportFrom": "Hurtig import fra",
"quickImport": "Hurtig import",
"quickImportAirtable": "Quick Import - Airtable",
"quickImportCSV": "Quick Import - CSV",
"quickImportExcel": "Quick Import - Excel",
"quickImportJSON": "Quick Import - JSON",
"jsonEditor": "JSON Editor",
"comingSoon": "Coming Soon",
"advancedSettings": "Avancerede indstillinger",
"codeSnippet": "Kodeuddrag",
"keyboardShortcut": "Tastaturgenveje",
"generateRandomName": "Generér Tilfældigt Navn",
"findRowByScanningCode": "Find row by scanning a QR or Barcode"
"findRowByScanningCode": "Find row by scanning a QR or Barcode",
"tokenManagement": "Token Management",
"addNewToken": "Add new token",
"accountSettings": "Account Settings",
"resetPasswordMenu": "Reset Password",
"tokens": "Tokens",
"userManagement": "User Management",
"accountManagement": "Account management",
"licence": "Licence",
"allowAllMimeTypes": "Allow All Mime Types",
"defaultView": "Default View",
"relations": "Relations",
"switchLanguage": "Switch Language",
"renameFile": "Rename File",
"links": {
"noAction": "No Action",
"cascade": "Cascade",
"restrict": "Restrict",
"setNull": "Set NULL",
"setDefault": "Set Default"
}
},
"labels": {
"heading1": "Heading 1",
"heading2": "Heading 2",
"heading3": "Heading 3",
"bold": "Bold",
"italic": "Italic",
"underline": "Underline",
"strike": "Strike",
"taskList": "Task List",
"bulletList": "Bullet List",
"numberedList": "Numbered List",
"downloadData": "Download Data",
"blockQuote": "Block Quote",
"noToken": "No Token",
"tokenLimit": "Only one token per user is allowed",
"duplicateAttachment": "File with name {filename} already attached",
"viewIdColon": "VIEW ID: {viewId}",
"toAddress": "To Address",
"subject": "Subject",
"body": "Body",
"commaSeparatedMobileNumber": "Comma separated Mobile #",
"headerName": "Header Name",
"icon": "Icon",
"max": "Max",
"enableRichText": "Enable Rich Text",
"idColon": "Id:",
"copiedRecordURL": "Copied Record URL",
"copyRecordURL": "Copy Record URL",
"duplicateRecord": "Duplicate record",
"binaryEncodingFormat": "Binary encoding format",
"syntax": "Syntax",
"examples": "Examples",
"durationInfo": "A duration of time in minutes or seconds (e.g. 1:23).",
"addHeader": "Add Header",
"enterDefaultUrlOptional": "Enter default URL (Optional)",
"negative": "Negative",
"discard": "Discard",
"default": "Default",
"defaultNumberPercent": "Default Number (%)",
"durationFormat": "Duration Format",
"dateFormat": "Date Format",
"timeFormat": "Time Format",
"singularLabel": "Singular Label",
"pluralLabel": "Plural Label",
"optional": "(Optional)",
"clickToMake": "Click to make",
"visibleForRole": "visible for role:",
"inUI": "in UI Dashboard",
"projectSettings": "Base Settings",
"clickToHide": "Click to hide",
"clickToDownload": "Click to download",
"forRole": "for role",
"clickToCopyViewID": "Click to copy View ID",
"viewMode": "View Mode",
"searchUsers": "Search Users",
"superAdmin": "Super Admin",
"allTables": "All Tables",
"members": "Members",
"dataSources": "Data Sources",
"connectDataSource": "Connect a Data Source",
"searchProjects": "Search Bases",
"createdBy": "Oprettet af",
"viewingAttachmentsOf": "Viewing Attachments of",
"readOnly": "Readonly",
"dropHere": "Drop here",
"createdOn": "Created On",
"notifyVia": "Bemærk Via.",
"projName": "Projekt navn",
"profile": "Profile",
"accountDetails": "Account Details",
"controlAppearance": "Control your Appearance.",
"accountEmailID": "Account Email ID",
"backToWorkspace": "Back to Workspace",
"untitledToken": "Untitled token",
"tableName": "Tabelnavn.",
"dashboardName": "Dashboard name",
"createView": "Create a View",
"creatingView": "Creating View",
"duplicateView": "Duplicate View",
"duplicateGridView": "Duplicate Grid View",
"createGridView": "Create Grid View",
"duplicateGalleryView": "Duplicate Gallery View",
"createGalleryView": "Create Gallery View",
"duplicateFormView": "Duplicate Form View",
"createFormView": "Create Form View",
"duplicateKanbanView": "Duplicate Kanban View",
"createKanbanView": "Create Kanban View",
"viewName": "Se navn",
"viewLink": "Vis Link",
"columnName": "Kolonne navn",
@ -247,6 +528,14 @@
"where": "Hvor",
"cache": "Cache",
"chat": "Snak",
"showOrHide": "Show or Hide",
"airtable": "Airtable",
"csv": "CSV",
"csvFile": "CSV File",
"json": "JSON",
"jsonFile": "JSON File",
"excel": "Excel",
"microsoftExcel": "Microsoft Excel",
"email": "E-mail.",
"storage": "Opbevaring",
"uiAcl": "UI-ACL",
@ -255,12 +544,13 @@
"created": "Oprettet",
"sqlOutput": "SQL Output.",
"addOption": "Tilføj option",
"interfaceColor": "Interface Color",
"qrCodeValueColumn": "Kolonne med QR-kodeværdi",
"barcodeValueColumn": "Kolonne med stregkodeværdi",
"barcodeFormat": "Stregkodeformat",
"qrCodeValueTooLong": "For mange tegn til en QR-kode",
"barcodeValueTooLong": "For mange tegn til en stregkode",
"currentLocation": "Current Location",
"currentLocation": "Aktuel placering",
"lng": "Lng",
"lat": "Lat",
"aggregateFunction": "Aggregate Function.",
@ -282,13 +572,17 @@
"joinDiscord": "Deltag Diskord",
"joinCommunity": "Tilmeld dig NocoDB-fællesskabet",
"joinReddit": "Deltag /r/NocoDB",
"followNocodb": "Følg NocoDB"
"followNocodb": "Følg NocoDB",
"communityTranslated": "(Community Translated)"
},
"twitter": "Twitter",
"docReference": "Dokumentreference.",
"selectUserRole": "Vælg brugerrolle",
"childTable": "Undertabel",
"childColumn": "Underkolonner",
"childField": "Child field",
"linkToAnotherRecord": "Link til en anden post",
"links": "Links",
"onUpdate": "På opdatering",
"onDelete": "På Delete.",
"account": "Konto",
@ -298,16 +592,21 @@
"customTheme": "Brugerdefineret tema",
"requestDataSource": "Har du brug for en datakilde, du har brug for?",
"apiKey": "API-nøgle",
"sharedBase": "Fælles base",
"personalAccessToken": "Personal Access Token",
"sharedBaseUrl": "Shared Base URL",
"importData": "Import af data",
"importSecondaryViews": "Import af sekundære visninger",
"importRollupColumns": "Import af kolonner i rulleskemaer",
"importLookupColumns": "Import af opslagssøjler",
"importAttachmentColumns": "Import af kolonner til vedhæftede filer",
"importFormulaColumns": "Import af formelkolonner",
"importUsers": "Import Users (by email)",
"noData": "Ingen data",
"goToDashboard": "Gå til Dashboard",
"importing": "Import af",
"formatJson": "Format JSON",
"autoSelectFieldTypes": "Auto-Select Field Types",
"firstRowAsHeaders": "Use First Record as Headers",
"flattenNested": "Flade, indlejrede",
"downloadAllowed": "Download tilladt",
"weAreHiring": "Vi ansætter!",
@ -325,9 +624,61 @@
"welcomeToNc": "Velkommen til NocoDB!",
"inviteOnlySignup": "Tillad kun tilmelding ved hjælp af inviteret url",
"nextRow": "Næste række",
"prevRow": "Forrige række"
"prevRow": "Forrige række",
"addRowGrid": "Manually add data in grid view",
"addRowForm": "Enter record data through a form",
"noAccess": "No access",
"restApis": "Rest APIs",
"apis": "APIs",
"includeData": "Include Data",
"includeView": "Include View",
"includeWebhook": "Include Webhook",
"zoomInToViewColumns": "Zoom in to view columns",
"embedInSite": "Embed this view in your site",
"titleRequired": "title is required.",
"sourceNameRequired": "Source name is required",
"changeWsName": "Change Workspace Name",
"pressEnter": "Press Enter",
"newFormLoaded": "New form will be loaded after"
},
"activity": {
"openInANewTab": "Open in a new tab",
"copyIFrameCode": "Copy IFrame code",
"onCondition": "On Condition",
"bulkDownload": "Bulk Download",
"attachFile": "Attach File",
"viewAttachment": "View Attachments",
"attachmentDrop": "Click or drop a file into cell",
"addFiles": "Add File(s)",
"hideInUI": "Hide in UI",
"addBase": "Add Base",
"addParameter": "Add Parameter",
"submitAnotherForm": "Submit Another Form",
"dragAndDropFieldsHereToAdd": "Drag and drop fields here to add",
"editSource": "Edit Data Source",
"enterText": "Enter text",
"okEditBase": "Ok & Edit Base",
"showInUI": "Show in UI",
"outOfSync": "Out of sync",
"newSource": "New Data Source",
"newWebhook": "New Webhook",
"enablePublicAccess": "Enable Public Access",
"doYouWantToSaveTheChanges": "Do you want to save the changes ?",
"editingAccess": "Editing access",
"enabledPublicViewing": "Enable public viewing",
"restrictAccessWithPassword": "Restrict access with password",
"manageProjectAccess": "Manage Base Access",
"allowDownload": "Allow Download",
"surveyMode": "Survey Mode",
"rtlOrientation": "RTL Orientation",
"useTheme": "Use Theme",
"copyLink": "Copy Link",
"copiedLink": "Link Copied",
"copyInviteLink": "Copy invite link",
"copiedInviteLink": "Copied invite link",
"copyUrl": "Kopier URL.",
"moreColors": "More Colors",
"moveProject": "Move Base",
"createProject": "Opret projekt",
"importProject": "Import Project.",
"searchProject": "Søg projekt",
@ -338,6 +689,7 @@
"deleteProject": "Slet projekt",
"refreshProject": "Opdater projekter",
"saveProject": "Gem projekt",
"saveAndQuit": "Save & Quit",
"deleteKanbanStack": "Slet stakken?",
"createProjectExtended": {
"extDB": "Opret ved at forbinde <br> til en ekstern database",
@ -353,6 +705,7 @@
"translate": "Hjælp Translate",
"account": {
"authToken": "Kopier Auth Token",
"authTokenCopied": "Copied Auth Token",
"swagger": "Swagger: REST API'er",
"projInfo": "Kopier projekt info.",
"themes": "Temaer."
@ -362,7 +715,10 @@
"filter": "Filter",
"addFilter": "Tilføj filter",
"share": "Del",
"groupBy": "Group By",
"addSubGroup": "Add subgroup",
"shareBase": {
"label": "Share base",
"disable": "Deaktiver delt base",
"enable": "Nogen med linket",
"link": "Shared Base Link."
@ -372,6 +728,8 @@
"inviteTeam": "Inviter Team.",
"inviteUser": "Inviter bruger",
"inviteToken": "Inviter token",
"linkedRecords": "Linked Records",
"addNewLink": "Add New Link",
"newUser": "Ny bruger",
"editUser": "Rediger bruger",
"deleteUser": "Fjern bruger fra projektet",
@ -386,9 +744,12 @@
"previousRecord": "Forrige post",
"copyApiURL": "COPY API URL.",
"createTable": "Create New Table",
"createDashboard": "Create Dashboard",
"createWorkspace": "Create Workspace",
"refreshTable": "Genopfrisk Tabeller",
"renameTable": "Rename Table",
"deleteTable": "Delete Table",
"renameTable": "Omdøb tabel",
"renameLayout": "Layout Rename",
"deleteTable": "Slet tabel",
"addField": "Tilføj nyt felt til denne tabel",
"setDisplay": "Sæt som visningsværdi",
"addRow": "Tilføj ny post",
@ -398,6 +759,9 @@
"insertRow": "Indsæt ny række",
"duplicateRow": "Dupliker Række",
"deleteRow": "Slet Række",
"deleteRows": "Delete records",
"predictColumns": "Predict Fields",
"predictFormulas": "Predict Formulas",
"deleteSelectedRow": "Slet de valgte rækker",
"importExcel": "Import Excel.",
"importCSV": "Import CSV.",
@ -413,11 +777,12 @@
"createView": "Opret en visning",
"shareView": "Del Visning",
"findRowByCodeScan": "Find row by scan",
"fillByCodeScan": "Fill by scan",
"fillByCodeScan": "Udfyld med scanning",
"listSharedView": "Shared View List.",
"ListView": "Visninger List",
"copyView": "Kopi visning",
"renameView": "Omdøb visning",
"uploadData": "Upload Data",
"deleteView": "Slet visning",
"createGrid": "Opret gridvisning",
"createGallery": "Opret Gallery View.",
@ -425,14 +790,13 @@
"createKanban": "Opret Kanban View.",
"createForm": "Opret formularvisning",
"showSystemFields": "Vis systemfelter",
"copyUrl": "Kopier URL.",
"openTab": "Åbn ny fane.",
"iFrame": "Kopier Embeddable HTML-kode",
"addWebhook": "Tilføj nyt webhook.",
"enableWebhook": "Enable Webhook",
"enableWebhook": "Aktiver Webhook",
"testWebhook": "Test Webhook",
"copyWebhook": "Copy Webhook",
"deleteWebhook": "Delete Webhook",
"copyWebhook": "Kopier webhook",
"deleteWebhook": "Slet Webhook",
"newToken": "Tilføj nyt token",
"exportZip": "Eksporter zip",
"importZip": "Import Zip.",
@ -451,10 +815,24 @@
"addFilterGroup": "Tilføj filtergruppe",
"linkRecord": "Link record",
"addNewRecord": "Tilføj ny post",
"newRecord": "New record",
"tableNameCreateNewRecord": "{tableName}: Create new record",
"gotSavedLinkedSuccessfully": "{tableName} '{recordTitle}' got saved & linked successfully",
"recordCreatedLinked": "Record Created & Linked",
"useConnectionUrl": "Brug forbindelses-URL",
"toggleCommentsDraw": "Toggle kommentarer tegne",
"expandRecord": "Udvid optegnelse",
"deleteRecord": "Slet Post",
"fullWidth": "Full width",
"exitFullWidth": "Exit full width",
"markAllAsRead": "Mark all as read",
"column": {
"delete": "Delete Field",
"addNumber": "Add Number Field",
"addSingleLineText": "Add SingleLineText Field",
"addLongText": "Add LongText Field",
"addOther": "Add Other Field"
},
"erd": {
"showColumns": "Vis kolonner",
"showPkAndFk": "Vis primære og fremmede nøgler",
@ -475,9 +853,11 @@
"openInGoogleMaps": "Google Maps",
"openInOpenStreetMap": "OSM"
},
"toggleMobileMode": "Toggle Mobile Mode"
"toggleMobileMode": "Skift Mobil Tilstand",
"startCommenting": "Start commenting!"
},
"tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment",
"saveChanges": "Gem ændringer",
"xcDB": "Opret et nyt projekt",
"extDB": "Understøtter MySQL, PostgreSQL, SQL Server & SQLITE",
@ -488,6 +868,7 @@
"light": "Kommer det i sort? (^ ⇧b)"
},
"addTable": "Tilføj nyt tabel",
"addDashboard": "Add new Dashboard",
"inviteMore": "Inviter flere brugere",
"toggleNavDraw": "Toggle navigation skuffe",
"reloadApiToken": "Genindlæs API Tokens",
@ -506,7 +887,19 @@
"clientCA": "Vælg CA File."
},
"placeholder": {
"selectSlackChannels": "Select Slack channels",
"selectTeamsChannels": "Select Microsoft Teams channels",
"selectDiscordChannels": "Select Discord channels",
"selectMattermostChannels": "Select Mattermost channels",
"webhookTitle": "Webhook Title",
"barcodeColumn": "Select a field for the Barcode value",
"notFoundContent": "No valid field Type can be found.",
"selectBarcodeFormat": "Select a Barcode format",
"projName": "Indtast projektnavn",
"selectGroupField": "Select a Grouping Field",
"selectGroupFieldNotFound": "No Single Select Field can be found. Please create one first.",
"selectGeoField": "Select a GeoData Field",
"selectGeoFieldNotFound": "No GeoData Field can be found. Please create one first.",
"password": {
"enter": "Indtast adgangskoden",
"current": "Nuværende kodeord",
@ -514,6 +907,8 @@
"save": "Gem adgangskode.",
"confirm": "Bekræft ny adgangskode"
},
"selectAColumnForTheQRCodeValue": "Select a field for the QR code value",
"allowNegativeNumbers": "Allow negative numbers",
"searchProjectTree": "Søg tabeller",
"searchFields": "Søgefelter.",
"searchColumn": "Søg {Søg} kolonne",
@ -523,26 +918,144 @@
"defaultValue": "Standard værdi",
"filterByEmail": "Filtrer efter e-mail",
"filterQuery": "Filter forespørgsel",
"selectField": "Vælg felt"
"selectField": "Vælg felt",
"precision": "Precision",
"decimal1": "1.0",
"decimal2": "1.00",
"decimal3": "1.000",
"decimal4": "1.0000",
"decimal5": "1.00000",
"decimal6": "1.000000",
"decimal7": "1.0000000",
"decimal8": "1.00000000",
"value": "Value",
"key": "Key"
},
"msg": {
"clickToCopyFieldId": "Click to copy Field Id",
"enterPassword": "Enter password",
"bySigningUp": "By signing up, you agree to the",
"subscribeToOurWeeklyNewsletter": "Subscribe to our weekly newsletter",
"verifyingPassword": "Verifying Password",
"thisSharedViewIsProtected": "This shared view is protected",
"successfullySubmittedFormData": "Successfully submitted form data",
"formViewNotSupportedOnMobile": "Form view is not supported on mobile",
"newFormWillBeLoaded": "New form will be loaded after {seconds} seconds",
"optimizedQueryDisabled": "Optimized query is disabled",
"optimizedQueryEnabled": "Optimized query is enabled",
"lookupNonBtWarning": "Lookup field is not supported for non-Belongs to relation",
"invalidTime": "Invalid Time",
"linkColumnClearNotSupportedYet": "You don't have any supported links for Lookup",
"recordCouldNotBeFound": "Record could not be found",
"invalidPhoneNumber": "Invalid phone number",
"pageSizeChanged": "Page size changed",
"errorLoadingData": "Error loading data",
"webhookBodyMsg1": "Use context variable",
"webhookBodyMsg2": "body",
"webhookBodyMsg3": "to refer the record under consideration",
"formula": {
"hintStart": "Hint: Use {placeholder1} to reference fields, e.g: {placeholder2}. For more, please check out",
"hintEnd": "Formulas.",
"noSuggestedFormulaFound": "No suggested formula found",
"numericTypeIsExpected": "Numeric type is expected",
"stringTypeIsExpected": "String type is expected",
"operationNotAvailable": "{operation} operation not available",
"cantSaveFieldFormulaInvalid": "Can’t save field because formula is invalid",
"notSupportedToReferenceColumn": "Not supported to reference field {columnName}",
"typeIsExpectedButFound": "Type {type} is expected but found Type {found}",
"requiredArgumentsFormula": "{calleeName} requires {requiredArguments} arguments",
"minRequiredArgumentsFormula": "{calleeName} required minimum {minRequiredArguments} arguments",
"maxRequiredArgumentsFormula": "{calleeName} required maximum {maxRequiredArguments} arguments",
"functionNotAvailable": "{function} function is not available",
"firstParamWeekDayHaveDate": "The first parameter of WEEKDAY() should have date value",
"secondParamWeekDayHaveDate": "The second parameter of WEEKDAY() should have the value either \"sunday\", \"monday\", \"tuesday\", \"wednesday\", \"thursday\", \"friday\" or \"saturday\"",
"firstParamDateAddHaveDate": "The first parameter of DATEADD() should have date value",
"secondParamDateAddHaveNumber": "The second parameter of DATEADD() should have numeric value",
"thirdParamDateAddHaveDate": "The third parameter of DATEADD() should have the value either \"day\", \"week\", \"month\" or \"year\"",
"firstParamDateDiffHaveDate": "The first parameter of DATEDIFF() should have date value",
"secondParamDateDiffHaveDate": "The second parameter of DATEDIFF() should have date value",
"thirdParamDateDiffHaveDate": "The third parameter of DATETIME_DIFF() should have value either \"milliseconds\", \"ms\", \"seconds\", \"s\", \"minutes\", \"m\", \"hours\", \"h\", \"days\", \"d\", \"weeks\", \"w\", \"months\", \"M\", \"quarters\", \"Q\", \"years\", or \"y\"",
"columnNotAvailable": "Field {columnName} is not available",
"cantSaveCircularReference": "Can’t save field because it causes a circular reference",
"columnWithTypeFoundButExpected": "Field {columnName} with {columnType} type is found but {expectedType} type is expected",
"columnNotMatchedWithType": "{columnName} is not matched with {columnType}"
},
"selectOption": {
"cantBeNull": "Select options can't be null",
"multiSelectCantHaveCommas": "MultiSelect fields can't have commas(',')",
"cantHaveDuplicates": "Select options can't have duplicates",
"createNewOptionNamed": "Create new option named"
},
"plsEnterANumber": "Please enter a number",
"plsInputEmail": "Please input email",
"invalidDate": "Invalid date",
"invalidLocale": "Invalid locale",
"invalidCurrencyCode": "Invalid Currency Code",
"postgresHasItsOwnCurrencySettings": "PostgreSQL 'money' type has own currency settings",
"validColumnsForBarCode": "The valid Field Types for a Barcode Field are: Number, Single Line Text, Long Text, Phone Number, URL, Email, Decimal. Please create one first.",
"hm": {
"title": "Has Many Relation",
"tooltip_desc": "A single record from table ",
"tooltip_desc2": " can be linked with multiple records from table "
},
"mm": {
"title": "Many to Many Relation",
"tooltip_desc": "Multiple records from table ",
"tooltip_desc2": " can be linked with multiple records from table "
},
"bt": {
"title": "Belongs to Relation",
"tooltip_desc": "A single record from table ",
"tooltip_desc2": " can be linked with a record from table "
},
"oo": {
"title": "One to One Relation",
"tooltip_desc": "A single record from table ",
"tooltip_desc2": " can be linked with a single record from table "
},
"noRecordsAreLinkedFromTable": "No records are linked from table",
"noRecordsLinked": "No records linked",
"recordsLinked": "records linked",
"acceptOnlyValid": "Accepts only",
"apiTokenCreate": "Create personal API tokens to use in automation or external apps.",
"selectFieldToSort": "Select Field to Sort",
"thereAreNoRecordsInTable": "There are no records in table",
"createWebhookMsg1": "Get started with web-hooks!",
"createWebhookMsg2": "Create web-hooks to power you automations,",
"createWebhookMsg3": "Get notified as soon as there are changes in your data",
"areYouSureUWantTo": "Are you sure you want to delete the following",
"areYouSureUWantToDeleteLabel": "Are you sure you want to {deleteLabel} the following",
"idColumnRequired": "ID field is required, you can rename this later if required.",
"length59Required": "The length exceeds the max 59 characters",
"noNewNotifications": "You have no new notifications",
"noRecordFound": "Record not found",
"rowDeleted": "Record deleted",
"saveChanges": "Do you want to save the changes?",
"tooLargeFieldEntity": "The field is too large to be converted to {entity}",
"roleRequired": "Role required",
"warning": {
"dbValid": "Please make sure database you are trying to connect is valid! This operation can cause schema loss!!",
"barcode": {
"renderError": "Stregkodefejl - kontroller kompatibiliteten mellem input og stregkodetype"
},
"nonEditableFields": {
"computedFieldUnableToClear": "Advarsel: Beregnet felt - ikke i stand til at slette teksten",
"qrFieldsCannotBeDirectlyChanged": "Advarsel: QR-felter kan ikke ændres direkte."
}
"qrFieldsCannotBeDirectlyChanged": "Advarsel: QR-felter kan ikke ændres direkte.",
"barcodeFieldsCannotBeDirectlyChanged": "Warning: Barcode fields cannot be directly changed."
},
"duplicateProject": "Are you sure you want to duplicate the base?",
"duplicateTable": "Are you sure you want to duplicate the table?"
},
"info": {
"disabledAsViewLocked": "Disabled as View is locked",
"basesMigrated": "Bases are migrated. Please try again.",
"pasteNotSupported": "Indsæt er ikke understøttet på den aktive celle",
"roles": {
"orgCreator": "Skaberen kan oprette nye projekter og få adgang til alle inviterede projekter.",
"orgViewer": "Seeren har ikke lov til at oprette nye projekter, men kan få adgang til alle inviterede projekter."
},
"codeScanner": {
"loadingScanner": "Loading the scanner...",
"loadingScanner": "Indlæsning af scanneren...",
"selectColumn": "Select a column (QR code or Barcode) that you want to use for finding a row by scanning.",
"moreThanOneRowFoundForCode": "More than one row found for this code. Currently only unique codes are supported.",
"noRowFoundForCode": "No row found for this code for the selected column"
@ -640,6 +1153,9 @@
"tablesMetadataInSync": "Tabeller Metadata er synkroniseret",
"addMultipleUsers": "Du kan tilføje flere komma (,) adskilte e-mails",
"enterTableName": "Indtast tabelnavn",
"enterLayoutName": "Enter Layout name",
"enterDashboardName": "Enter Dashboard name",
"defaultColumns": "Default fields",
"addDefaultColumns": "Tilføj standard kolonner",
"tableNameInDb": "Tabelnavn som gemt i databasen",
"airtable": {
@ -662,30 +1178,54 @@
"valueAlreadyInList": "Denne værdi findes allerede på listen",
"noColumnsToUpdate": "Ingen kolonner, der skal opdateres",
"tableDeleted": "Slettet tabel med succes",
"layoutDeleted": "Deleted layout successfully",
"generatePublicShareableReadonlyBase": "Generer en offentlig delbar skrivebeskyttet base",
"deleteViewConfirmation": "Er du sikker på, at du vil slette denne visning?",
"deleteLayoutConfirmation": "Are you sure you want to delete this Layout?",
"deleteTableConfirmation": "Ønsker du at slette tabellen",
"showM2mTables": "Vis M2M-tabeller",
"showM2mTablesDesc": "Mange-til-mange-relationer understøttes via en sammenknytnings-tabel (junction table) og er skjult som standard. Aktiver denne indstilling for at få vist alle sådanne tabeller sammen med eksisterende tabeller.",
"showNullInCells": "Vis NULL i celler",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullInCellsDesc": "Vis 'NULL' tag i celler med NULL værdi. Dette hjælper med at differentiere mod celler med UDEN tekst.",
"showNullAndEmptyInFilter": "Vis NULL og EMPTY i Filter",
"showNullAndEmptyInFilterDesc": "Aktiver \"yderligere\" filtre for at skelne mellem felter, der indeholder NULL og tomme strenge. Standardunderstøttelse for Blank behandler både NULL- og tomme strenge ens.",
"deleteKanbanStackConfirmation": "Hvis du sletter denne stak, fjernes også valgmuligheden `{stackToBeDeleted}` fra `{groupingField}`. Posterne vil blive flyttet til stakken \"uncategorized\".",
"computedFieldEditWarning": "Beregnet felt: indholdet er skrivebeskyttet. Brug kolonne-redigeringsmenuen til at omkonfigurere",
"computedFieldDeleteWarning": "Beregnet felt: indholdet er skrivebeskyttet. Det er ikke muligt at slette indholdet.",
"noMoreRecords": "Ikke flere optegnelser"
"noMoreRecords": "Ikke flere optegnelser",
"tokenNameNotEmpty": "Token name should not be empty",
"tokenNameMaxLength": "Token name should not be more than 255 characters",
"dbNameRequired": "Database name is required",
"wsNameRequired": "Workspace name required",
"wsNameMinLength": "Workspace name must be at least 3 characters long",
"wsNameMaxLength": "Workspace name must be at most 50 characters long",
"wsDeleteDlg": "Delete this workspace and all it’s contents.",
"userConfirmation": "I understand that this action is irreversible",
"pageNotFound": "Page Not Found",
"makeLineBreak": "to make a line break",
"goToPrevious": "Go to previous",
"goToNext": "Go to next",
"thankYou": "Thank you!",
"submittedFormData": "You have successfully submitted the form data."
},
"error": {
"nameRequired": "Name Required",
"nameMinLength": "Name must be at least 2 characters long",
"nameMaxLength": "Name must be at most 60 characters long",
"viewNameRequired": "View name is required",
"nameMaxLength256": "Name must be at most 256 characters long",
"viewNameUnique": "View name should be unique",
"searchProject": "Din søgning efter {Søg} viste ingen resultater",
"invalidChar": "Ugyldig tegn i mappebanen.",
"invalidDbCredentials": "Ugyldige databaseoplysninger.",
"unableToConnectToDb": "Kan ikke oprette forbindelse til databasen, tjek venligst din database er op.",
"invalidYear": "Invalid year",
"userDoesntHaveSufficientPermission": "Brugeren eksisterer ikke eller har tilstrækkelig tilladelse til at skabe skema.",
"dbConnectionStatus": "Ugyldige databaseparametre",
"dbConnectionFailed": "Forbindelsesfejl:",
"nullFilterExists": "Null filter exists. Please remove them",
"signUpRules": {
"emailReqd": "E-mail er påkrævet",
"emailRequired": "Email is required",
"emailInvalid": "E-mail skal være gyldig",
"passwdRequired": "adgangskode er påkrævet",
"passwdLength": "Din adgangskode skal være mindst 8 tegn",
@ -695,10 +1235,12 @@
"atLeastOneUppercase": "Et stort bogstav",
"atLeastOneNumber": "Et nummer",
"atLeastOneSpecialChar": "Et specialtegn",
"allowedSpecialCharList": "Liste over tilladte specialtegn"
"allowedSpecialCharList": "Liste over tilladte specialtegn",
"invalidEmails": "Invalid emails",
"invalidEmail": "Invalid Email"
},
"invalidURL": "Ugyldig URL",
"invalidEmail": "Invalid Email",
"invalidEmail": "Ugyldig e-mail",
"internalError": "Der er opstået en intern fejl",
"templateGeneratorNotFound": "Template Generator kan ikke findes!",
"fileUploadFailed": "Det er ikke lykkedes at uploade filen",
@ -726,6 +1268,8 @@
"nameShouldStartWithAnAlphabetOr_": "Navnet skal starte med et alfabet eller _",
"followingCharactersAreNotAllowed": "Følgende tegn er ikke tilladt",
"columnNameRequired": "Kolonnens navn er påkrævet",
"duplicateColumnName": "Duplicate field name",
"uiDataTypeRequired": "UI data type is required",
"columnNameExceedsCharacters": "Længden af kolonnenavnet overstiger maks. {value} tegn",
"projectNameExceeds50Characters": "Projektnavnet overstiger 50 tegn",
"projectNameCannotStartWithSpace": "Projektnavnet kan ikke begynde med et mellemrum",
@ -758,6 +1302,7 @@
"futureRelease": "Kommer snart!"
},
"success": {
"licenseKeyUpdated": "License Key Updated",
"columnDuplicated": "Kolonne duplikeret med succes",
"rowDuplicatedWithoutSavedYet": "Række duplikeret (ikke gemt)",
"updatedUIACL": "Opdateret UI ACL for tabeller med succes",
@ -765,6 +1310,7 @@
"pluginSettingsSaved": "Plugin-indstillingerne er gemt med succes",
"pluginTested": "Succesfuldt testet plugin-indstillinger",
"tableRenamed": "Det er lykkedes at omdøbe tabellen",
"layoutRenamed": "Layout renamed successfully",
"viewDeleted": "Vis slettet med succes",
"primaryColumnUpdated": "Succesfuldt opdateret som primær kolonne",
"tableDataExported": "Det er lykkedes at eksportere alle tabeldata",
@ -779,7 +1325,7 @@
"userDeletedFromProject": "Det er lykkedes at slette brugeren fra projektet",
"inviteEmailSent": "E-mail med invitation sendt med succes",
"inviteURLCopied": "Inviter URL kopieret til udklipsholderen",
"commentCopied": "Comment copied to clipboard",
"commentCopied": "Kommentar kopieret til udklipsholder",
"passwordResetURLCopied": "URL til nulstilling af adgangskode kopieret til udklipsholderen",
"shareableURLCopied": "Kopieret delbar basis-URL til udklipsholderen!",
"embeddableHTMLCodeCopied": "Kopieret HTML-kode, der kan indlejres!",

666
packages/nc-gui/lang/de.json

File diff suppressed because it is too large Load Diff

33
packages/nc-gui/lang/en.json

@ -75,6 +75,7 @@
"matterMost": "Mattermost",
"twilio": "Twilio",
"whatsappTwilio": "WhatsApp Twilio",
"quote": "Quote",
"submit": "Submit",
"create": "Create",
"createEntity": "Create {entity}",
@ -82,6 +83,7 @@
"creatingEntity": "Creating {entity}",
"details": "Details",
"skip": "Skip",
"code": "Code",
"duplicate": "Duplicate",
"duplicating": "Duplicating",
"activate": "Activate",
@ -227,7 +229,7 @@
"editor": "Editor",
"commenter": "Commenter",
"viewer": "Viewer",
"noaccess":"No Access",
"noaccess": "No Access",
"superAdmin": "Super Admin",
"orgLevelCreator": "Organization Level Creator",
"orgLevelViewer": "Organization Level Viewer"
@ -411,7 +413,18 @@
}
},
"labels": {
"heading1": "Heading 1",
"heading2": "Heading 2",
"heading3": "Heading 3",
"bold": "Bold",
"italic": "Italic",
"underline": "Underline",
"strike": "Strike",
"taskList": "Task List",
"bulletList": "Bullet List",
"numberedList": "Numbered List",
"downloadData": "Download Data",
"blockQuote": "Block Quote",
"noToken": "No Token",
"tokenLimit": "Only one token per user is allowed",
"duplicateAttachment": "File with name {filename} already attached",
@ -423,6 +436,7 @@
"headerName": "Header Name",
"icon": "Icon",
"max": "Max",
"enableRichText": "Enable Rich Text",
"idColon": "Id:",
"copiedRecordURL": "Copied Record URL",
"copyRecordURL": "Copy Record URL",
@ -591,6 +605,7 @@
"goToDashboard": "Go to Dashboard",
"importing": "Importing",
"formatJson": "Format JSON",
"autoSelectFieldTypes": "Auto-Select Field Types",
"firstRowAsHeaders": "Use First Record as Headers",
"flattenNested": "Flatten Nested",
"downloadAllowed": "Download allowed",
@ -713,6 +728,8 @@
"inviteTeam": "Invite Team",
"inviteUser": "Invite User",
"inviteToken": "Invite Token",
"linkedRecords": "Linked Records",
"addNewLink": "Add New Link",
"newUser": "New User",
"editUser": "Edit user",
"deleteUser": "Remove user from base",
@ -799,6 +816,9 @@
"linkRecord": "Link record",
"addNewRecord": "Add new record",
"newRecord": "New record",
"tableNameCreateNewRecord": "{tableName}: Create new record",
"gotSavedLinkedSuccessfully": "{tableName} '{recordTitle}' got saved & linked successfully",
"recordCreatedLinked": "Record Created & Linked",
"useConnectionUrl": "Use Connection URL",
"toggleCommentsDraw": "Toggle comments draw",
"expandRecord": "Expand Record",
@ -806,12 +826,12 @@
"fullWidth": "Full width",
"exitFullWidth": "Exit full width",
"markAllAsRead": "Mark all as read",
"column":{
"column": {
"delete": "Delete Field",
"addNumber": "Add Number Field",
"addSingleLineText": "Add SingleLineText Field",
"addLongText": "Add LongText Field",
"addOther":"Add Other Field"
"addOther": "Add Other Field"
},
"erd": {
"showColumns": "Show Fields",
@ -1027,6 +1047,7 @@
"duplicateTable": "Are you sure you want to duplicate the table?"
},
"info": {
"disabledAsViewLocked": "Disabled as View is locked",
"basesMigrated": "Bases are migrated. Please try again.",
"pasteNotSupported": "Paste operation is not supported on the active cell",
"roles": {
@ -1175,9 +1196,9 @@
"tokenNameNotEmpty": "Token name should not be empty",
"tokenNameMaxLength": "Token name should not be more than 255 characters",
"dbNameRequired": "Database name is required",
"wsNameRequired":"Workspace name required",
"wsNameMinLength":"Workspace name must be at least 3 characters long",
"wsNameMaxLength":"Workspace name must be at most 50 characters long",
"wsNameRequired": "Workspace name required",
"wsNameMinLength": "Workspace name must be at least 3 characters long",
"wsNameMaxLength": "Workspace name must be at most 50 characters long",
"wsDeleteDlg": "Delete this workspace and all it’s contents.",
"userConfirmation": "I understand that this action is irreversible",
"pageNotFound": "Page Not Found",

640
packages/nc-gui/lang/es.json

File diff suppressed because it is too large Load Diff

584
packages/nc-gui/lang/eu.json

@ -1,5 +1,45 @@
{
"dashboards": {
"create_new_dashboard_project": "Create New Interface",
"connect_data_sources": "Connect data sources",
"alert": "Alert",
"alert-message": "No databases have been connected. Connect database bases to build interfaces. Skip this step and add databases from the base home page later.",
"select_database_projects_that_you_want_to_link_to_this_dashboard_projects": "Select Database Bases that you want to link to this Interface.",
"create_interface": "Create interface",
"project_name": "Base Name",
"connect": "Connect",
"buttonActionTypes": {
"open_external_url": "Open external link",
"delete_record": "Delete record",
"update_record": "Update record",
"open_layout": "Open layout"
},
"widgets": {
"static_text": "Text",
"chart": "Chart",
"table": "Table",
"image": "Image",
"map": "Map",
"button": "Button",
"number": "Number",
"bar_chart": "Bar Chart",
"line_chart": "Line Chart",
"area_chart": "Area Chart",
"pie_chart": "Pie Chart",
"donut_chart": "Donut Chart",
"scatter_plot": "Scatter Plot",
"bubble_chart": "Bubble Chart",
"radar_chart": "Radar Chart",
"polar_area_chart": "Polar Area Chart",
"radial_bar_chart": "Radial Bar Chart",
"heatmap_chart": "Heatmap Chart",
"treemap_chart": "Treemap Chart",
"box_plot_chart": "Box Plot Chart",
"candlestick_chart": "Candlestick Chart"
}
},
"general": {
"quit": "Quit",
"home": "Hasiera",
"load": "Kargatu",
"open": "Ireki",
@ -7,27 +47,67 @@
"yes": "Bai",
"no": "Ez",
"ok": "Ados",
"back": "Back",
"and": "Eta",
"or": "Edo",
"add": "Gehitu",
"edit": "Editatu",
"link": "Link",
"links": "Links",
"remove": "Ezabatu",
"import": "Import",
"logout": "Log Out",
"empty": "Empty",
"changeIcon": "Change Icon",
"save": "Gorde",
"available": "Available",
"abort": "Abort",
"saving": "Saving",
"cancel": "Ezeztatu",
"null": "Null",
"escape": "Escape",
"hex": "Hex",
"clear": "Clear",
"slack": "Slack",
"comment": "Comment",
"microsoftTeams": "Microsoft Teams",
"discord": "Discord",
"matterMost": "Mattermost",
"twilio": "Twilio",
"whatsappTwilio": "WhatsApp Twilio",
"quote": "Quote",
"submit": "Bidali",
"create": "Sortu",
"createEntity": "Create {entity}",
"creating": "Creating",
"creatingEntity": "Creating {entity}",
"details": "Details",
"skip": "Skip",
"code": "Code",
"duplicate": "Bikoiztu",
"duplicating": "Duplicating",
"activate": "Activate",
"action": "Action",
"insert": "Txertatu",
"delete": "Ezabatu",
"deleteEntity": "Delete {entity}",
"bulkInsert": "Bulk Insert",
"bulkDelete": "Bulk Delete",
"bulkUpdate": "Bulk Update",
"deleting": "Deleting",
"update": "Eguneratu",
"rename": "Berrizendatu",
"reload": "Birkargatu",
"reset": "Berrezarri",
"install": "Instalatu",
"show": "Erakutsi",
"access": "Access",
"visibility": "Visibility",
"hide": "Ezkutatu",
"deprecated": "Deprecated",
"showAll": "Dena erakutsi",
"hideAll": "Ezkutatu dena",
"notFound": "Not found",
"showMore": "Erakutsi gehiago",
"showOptions": "Erakutsi aukerak",
"hideOptions": "Ezkutatu aukerak",
@ -47,6 +127,8 @@
"upload": "Igo",
"download": "Deskargatu",
"default": "Lehenetsia",
"base": "Source",
"datasource": "Data Source",
"more": "Gehiago",
"less": "Gutxiago",
"event": "Gertaera",
@ -54,12 +136,14 @@
"after": "Ondoren",
"before": "Aurretik",
"search": "Bilatu",
"searchIn": "Search In",
"notification": "Jakinarazpena",
"reference": "Erreferentzia",
"function": "Funtzioa",
"confirm": "Berretsi",
"generate": "Generate",
"copy": "Kopiatu",
"are": "are",
"misc": "Miszelanea",
"lock": "Blokeatu",
"unlock": "Desblokeatu",
@ -76,9 +160,39 @@
"hideField": "Ezkutatu eremua",
"sortAsc": "Ordenatu gorantz",
"sortDesc": "Ordenatu beherantz",
"geoDataField": "GeoData Field"
"move": "Move",
"geoDataField": "GeoData Field",
"type": "Type",
"name": "Name",
"changes": "Changes",
"new": "New",
"old": "Old",
"data": "Data",
"source": "Source",
"destination": "Destination",
"active": "Active",
"inactive": "Inactive",
"linked": "linked",
"finish": "Finish",
"min": "Min",
"max": "Max",
"avg": "Avg",
"sum": "Sum",
"count": "Count",
"countDistinct": "Count Distinct",
"sumDistinct": "Sum Distinct",
"avgDistinct": "Avg Distinct",
"join": "Join",
"options": "Options",
"primaryValue": "Primary Value",
"useSurveyMode": "Use Survey Mode",
"shift": "Shift",
"enter": "Enter",
"seconds": "Seconds"
},
"objects": {
"workspace": "Workspace",
"workspaces": "Workspaces",
"project": "Proiektua",
"projects": "Proiektuak",
"table": "Taula",
@ -95,6 +209,7 @@
"webhooks": "Webhookak",
"view": "Bistaratu",
"views": "Bistaratzeak",
"sidebar": "Sidebar",
"viewType": {
"grid": "Grid",
"gallery": "Galeria",
@ -107,16 +222,27 @@
"users": "Erabiltzaileak",
"role": "Rola",
"roles": "Rolak",
"developer": "Developer",
"roleType": {
"owner": "Jabea",
"creator": "Sortzailea",
"editor": "Editorea",
"commenter": "Iruzkinlaria",
"viewer": "Ikuslea",
"noaccess": "No Access",
"superAdmin": "Super Admin",
"orgLevelCreator": "Organization Level Creator",
"orgLevelViewer": "Organization Level Viewer"
},
"sqlVIew": "SQL View"
"sqlVIew": "SQL View",
"rowHeight": "Record Height",
"heightClass": {
"short": "Short",
"medium": "Medium",
"tall": "Tall",
"extra": "Extra"
},
"externalDb": "External Database"
},
"datatype": {
"ID": "ID",
@ -171,17 +297,63 @@
"isNotNull": "is not null"
},
"title": {
"docs": "Docs",
"forum": "Forum",
"parameter": "Parameter",
"headers": "Headers",
"parameterName": "Parameter Name",
"currencyLocale": "Currency Locale",
"currencyCode": "Currency Code",
"searchMembers": "Search Members",
"noMembersFound": "No members found",
"dateJoined": "Date Joined",
"tokenName": "Token name",
"inDesktop": "in Desktop",
"rowData": "Record data",
"creator": "Creator",
"qrCode": "QR Code",
"termsOfService": "Terms of Service",
"updateSelectedRows": "Update Selected Records",
"noFiltersAdded": "No filters added",
"editCards": "Edit Cards",
"noFieldsFound": "No fields found",
"displayValue": "Display Value",
"expand": "Expand",
"hideAll": "Hide all",
"hideSystemFields": "Hide system fields",
"removeFile": "Remove File",
"hasMany": "Has Many",
"manyToMany": "Many to Many",
"virtualRelation": "Virtual Relation",
"linkMore": "Link More",
"linkMoreRecords": "Link more records",
"downloadFile": "Download File",
"renameTable": "Rename Table",
"renamingTable": "Renaming Table",
"renamingWs": "Renaming Workspace",
"renameWs": "Rename Workspace",
"deleteWs": "Delete Workspace",
"deletingWs": "Deleting Workspace",
"copyAuthToken": "Copy Auth Token",
"copiedAuthToken": "Copied Auth Token",
"copyInviteToken": "Copy Invite Token",
"showSidebar": "Show Sidebar",
"hideSidebar": "Hide Sidebar",
"creatingTable": "Creating Table",
"erdView": "ERD View",
"newBase": "New Data Source",
"newProj": "New Project",
"createBase": "Create Base",
"myProject": "My Projects",
"formTitle": "Form Title",
"collabView": "Collaborative View",
"lockedView": "Locked View",
"personalView": "Personal View",
"collaborative": "Collaborative",
"locked": "Locked",
"personal": "Personal",
"appStore": "App Store",
"teamAndAuth": "Team & Auth",
"rolesUserMgmt": "Roles & Users Management",
"userMgmt": "Users Management",
"apiTokens": "API Tokens",
"apiTokenMgmt": "API Tokens Management",
"rolesMgmt": "Roles Management",
"projMeta": "Project Metadata",
@ -204,20 +376,129 @@
"generateToken": "Sortu tokena",
"APIsAndSupport": "APIak & laguntza",
"helpCenter": "Laguntza gunea",
"noLabels": "No Labels",
"swaggerDocumentation": "Swagger Documentation",
"quickImportFrom": "Quick Import From",
"quickImport": "Quick Import",
"quickImportAirtable": "Quick Import - Airtable",
"quickImportCSV": "Quick Import - CSV",
"quickImportExcel": "Quick Import - Excel",
"quickImportJSON": "Quick Import - JSON",
"jsonEditor": "JSON Editor",
"comingSoon": "Coming Soon",
"advancedSettings": "Ezarpen aurreratuak",
"codeSnippet": "Kode-zatiak",
"keyboardShortcut": "Teklatuko laster-markak",
"generateRandomName": "Generate Random Name",
"findRowByScanningCode": "Find row by scanning a QR or Barcode"
"findRowByScanningCode": "Find row by scanning a QR or Barcode",
"tokenManagement": "Token Management",
"addNewToken": "Add new token",
"accountSettings": "Account Settings",
"resetPasswordMenu": "Reset Password",
"tokens": "Tokens",
"userManagement": "User Management",
"accountManagement": "Account management",
"licence": "Licence",
"allowAllMimeTypes": "Allow All Mime Types",
"defaultView": "Default View",
"relations": "Relations",
"switchLanguage": "Switch Language",
"renameFile": "Rename File",
"links": {
"noAction": "No Action",
"cascade": "Cascade",
"restrict": "Restrict",
"setNull": "Set NULL",
"setDefault": "Set Default"
}
},
"labels": {
"heading1": "Heading 1",
"heading2": "Heading 2",
"heading3": "Heading 3",
"bold": "Bold",
"italic": "Italic",
"underline": "Underline",
"strike": "Strike",
"taskList": "Task List",
"bulletList": "Bullet List",
"numberedList": "Numbered List",
"downloadData": "Download Data",
"blockQuote": "Block Quote",
"noToken": "No Token",
"tokenLimit": "Only one token per user is allowed",
"duplicateAttachment": "File with name {filename} already attached",
"viewIdColon": "VIEW ID: {viewId}",
"toAddress": "To Address",
"subject": "Subject",
"body": "Body",
"commaSeparatedMobileNumber": "Comma separated Mobile #",
"headerName": "Header Name",
"icon": "Icon",
"max": "Max",
"enableRichText": "Enable Rich Text",
"idColon": "Id:",
"copiedRecordURL": "Copied Record URL",
"copyRecordURL": "Copy Record URL",
"duplicateRecord": "Duplicate record",
"binaryEncodingFormat": "Binary encoding format",
"syntax": "Syntax",
"examples": "Examples",
"durationInfo": "A duration of time in minutes or seconds (e.g. 1:23).",
"addHeader": "Add Header",
"enterDefaultUrlOptional": "Enter default URL (Optional)",
"negative": "Negative",
"discard": "Discard",
"default": "Default",
"defaultNumberPercent": "Default Number (%)",
"durationFormat": "Duration Format",
"dateFormat": "Date Format",
"timeFormat": "Time Format",
"singularLabel": "Singular Label",
"pluralLabel": "Plural Label",
"optional": "(Optional)",
"clickToMake": "Click to make",
"visibleForRole": "visible for role:",
"inUI": "in UI Dashboard",
"projectSettings": "Base Settings",
"clickToHide": "Click to hide",
"clickToDownload": "Click to download",
"forRole": "for role",
"clickToCopyViewID": "Click to copy View ID",
"viewMode": "View Mode",
"searchUsers": "Search Users",
"superAdmin": "Super Admin",
"allTables": "All Tables",
"members": "Members",
"dataSources": "Data Sources",
"connectDataSource": "Connect a Data Source",
"searchProjects": "Search Bases",
"createdBy": "Sortzailea:",
"viewingAttachmentsOf": "Viewing Attachments of",
"readOnly": "Readonly",
"dropHere": "Drop here",
"createdOn": "Created On",
"notifyVia": "Jakinarazi nazazu honekin:",
"projName": "Proiektuaren izena",
"profile": "Profile",
"accountDetails": "Account Details",
"controlAppearance": "Control your Appearance.",
"accountEmailID": "Account Email ID",
"backToWorkspace": "Back to Workspace",
"untitledToken": "Untitled token",
"tableName": "Taularen izena",
"dashboardName": "Dashboard name",
"createView": "Create a View",
"creatingView": "Creating View",
"duplicateView": "Duplicate View",
"duplicateGridView": "Duplicate Grid View",
"createGridView": "Create Grid View",
"duplicateGalleryView": "Duplicate Gallery View",
"createGalleryView": "Create Gallery View",
"duplicateFormView": "Duplicate Form View",
"createFormView": "Create Form View",
"duplicateKanbanView": "Duplicate Kanban View",
"createKanbanView": "Create Kanban View",
"viewName": "Ikusi izena",
"viewLink": "Ikusi esteka",
"columnName": "Zutabearen izena",
@ -247,6 +528,14 @@
"where": "Where",
"cache": "Cache",
"chat": "Chat",
"showOrHide": "Show or Hide",
"airtable": "Airtable",
"csv": "CSV",
"csvFile": "CSV File",
"json": "JSON",
"jsonFile": "JSON File",
"excel": "Excel",
"microsoftExcel": "Microsoft Excel",
"email": "E-mail",
"storage": "Storage",
"uiAcl": "UI-ACL",
@ -255,6 +544,7 @@
"created": "Created",
"sqlOutput": "SQL Output",
"addOption": "Gehitu aukera",
"interfaceColor": "Interface Color",
"qrCodeValueColumn": "Column with QR code value",
"barcodeValueColumn": "Column with Barcode value",
"barcodeFormat": "Barcode format",
@ -282,13 +572,17 @@
"joinDiscord": "Join Discord",
"joinCommunity": "Join NocoDB Community",
"joinReddit": "Join /r/NocoDB",
"followNocodb": "Follow NocoDB"
"followNocodb": "Follow NocoDB",
"communityTranslated": "(Community Translated)"
},
"twitter": "Twitter",
"docReference": "Document Reference",
"selectUserRole": "Select User Role",
"childTable": "Child table",
"childColumn": "Child column",
"childField": "Child field",
"linkToAnotherRecord": "Link to another record",
"links": "Links",
"onUpdate": "On Update",
"onDelete": "On Delete",
"account": "Account",
@ -298,16 +592,21 @@
"customTheme": "Custom Theme",
"requestDataSource": "Request a data source you need?",
"apiKey": "API Key",
"sharedBase": "Shared Base",
"personalAccessToken": "Personal Access Token",
"sharedBaseUrl": "Shared Base URL",
"importData": "Import Data",
"importSecondaryViews": "Import Secondary Views",
"importRollupColumns": "Import Rollup Columns",
"importLookupColumns": "Import Lookup Columns",
"importAttachmentColumns": "Import Attachment Columns",
"importFormulaColumns": "Import Formula Columns",
"importUsers": "Import Users (by email)",
"noData": "No Data",
"goToDashboard": "Go to Dashboard",
"importing": "Importing",
"formatJson": "Format JSON",
"autoSelectFieldTypes": "Auto-Select Field Types",
"firstRowAsHeaders": "Use First Record as Headers",
"flattenNested": "Flatten Nested",
"downloadAllowed": "Download allowed",
"weAreHiring": "We are Hiring!",
@ -319,15 +618,67 @@
"commentsOnly": "Comments only",
"documentation": "Documentation",
"subscribeNewsletter": "Subscribe to our weekly newsletter",
"signUpWithGoogle": "Sign up with Google",
"signInWithGoogle": "Sign in with Google",
"signUpWithProvider": "Sign up with {provider}",
"signInWithProvider": "Sign in with {provider}",
"agreeToTos": "By signing up, you agree to the Terms of Service",
"welcomeToNc": "Welcome to NocoDB!",
"inviteOnlySignup": "Allow signup only using invite url",
"nextRow": "Next Row",
"prevRow": "Previous Row"
"prevRow": "Previous Row",
"addRowGrid": "Manually add data in grid view",
"addRowForm": "Enter record data through a form",
"noAccess": "No access",
"restApis": "Rest APIs",
"apis": "APIs",
"includeData": "Include Data",
"includeView": "Include View",
"includeWebhook": "Include Webhook",
"zoomInToViewColumns": "Zoom in to view columns",
"embedInSite": "Embed this view in your site",
"titleRequired": "title is required.",
"sourceNameRequired": "Source name is required",
"changeWsName": "Change Workspace Name",
"pressEnter": "Press Enter",
"newFormLoaded": "New form will be loaded after"
},
"activity": {
"openInANewTab": "Open in a new tab",
"copyIFrameCode": "Copy IFrame code",
"onCondition": "On Condition",
"bulkDownload": "Bulk Download",
"attachFile": "Attach File",
"viewAttachment": "View Attachments",
"attachmentDrop": "Click or drop a file into cell",
"addFiles": "Add File(s)",
"hideInUI": "Hide in UI",
"addBase": "Add Base",
"addParameter": "Add Parameter",
"submitAnotherForm": "Submit Another Form",
"dragAndDropFieldsHereToAdd": "Drag and drop fields here to add",
"editSource": "Edit Data Source",
"enterText": "Enter text",
"okEditBase": "Ok & Edit Base",
"showInUI": "Show in UI",
"outOfSync": "Out of sync",
"newSource": "New Data Source",
"newWebhook": "New Webhook",
"enablePublicAccess": "Enable Public Access",
"doYouWantToSaveTheChanges": "Do you want to save the changes ?",
"editingAccess": "Editing access",
"enabledPublicViewing": "Enable public viewing",
"restrictAccessWithPassword": "Restrict access with password",
"manageProjectAccess": "Manage Base Access",
"allowDownload": "Allow Download",
"surveyMode": "Survey Mode",
"rtlOrientation": "RTL Orientation",
"useTheme": "Use Theme",
"copyLink": "Copy Link",
"copiedLink": "Link Copied",
"copyInviteLink": "Copy invite link",
"copiedInviteLink": "Copied invite link",
"copyUrl": "Copy URL",
"moreColors": "More Colors",
"moveProject": "Move Base",
"createProject": "Create Project",
"importProject": "Import Project",
"searchProject": "Search Project",
@ -338,6 +689,7 @@
"deleteProject": "Delete Project",
"refreshProject": "Refresh projects",
"saveProject": "Save Project",
"saveAndQuit": "Save & Quit",
"deleteKanbanStack": "Delete stack?",
"createProjectExtended": {
"extDB": "Create By Connecting <br>To An External Database",
@ -353,6 +705,7 @@
"translate": "Help translate",
"account": {
"authToken": "Copy Auth Token",
"authTokenCopied": "Copied Auth Token",
"swagger": "Swagger: REST APIs",
"projInfo": "Copy Project Info",
"themes": "Themes"
@ -362,7 +715,10 @@
"filter": "Filter",
"addFilter": "Add Filter",
"share": "Share",
"groupBy": "Group By",
"addSubGroup": "Add subgroup",
"shareBase": {
"label": "Share base",
"disable": "Disable shared base",
"enable": "Anyone with the link",
"link": "Shared base link"
@ -372,6 +728,8 @@
"inviteTeam": "Invite Team",
"inviteUser": "Invite User",
"inviteToken": "Invite Token",
"linkedRecords": "Linked Records",
"addNewLink": "Add New Link",
"newUser": "New User",
"editUser": "Edit user",
"deleteUser": "Remove user from project",
@ -386,8 +744,11 @@
"previousRecord": "Previous record",
"copyApiURL": "Copy API URL",
"createTable": "Create New Table",
"createDashboard": "Create Dashboard",
"createWorkspace": "Create Workspace",
"refreshTable": "Tables Refresh",
"renameTable": "Rename Table",
"renameLayout": "Layout Rename",
"deleteTable": "Delete Table",
"addField": "Add new field to this table",
"setDisplay": "Set as Display value",
@ -398,6 +759,9 @@
"insertRow": "Insert New Row",
"duplicateRow": "Duplicate Row",
"deleteRow": "Delete Row",
"deleteRows": "Delete records",
"predictColumns": "Predict Fields",
"predictFormulas": "Predict Formulas",
"deleteSelectedRow": "Delete Selected Rows",
"importExcel": "Import Excel",
"importCSV": "Import CSV",
@ -418,6 +782,7 @@
"ListView": "Views List",
"copyView": "Copy view",
"renameView": "Rename view",
"uploadData": "Upload Data",
"deleteView": "Delete view",
"createGrid": "Create Grid View",
"createGallery": "Create Gallery View",
@ -425,7 +790,6 @@
"createKanban": "Create Kanban View",
"createForm": "Create Form View",
"showSystemFields": "Show system fields",
"copyUrl": "Copy URL",
"openTab": "Open new tab",
"iFrame": "Copy embeddable HTML code",
"addWebhook": "Add New Webhook",
@ -451,10 +815,24 @@
"addFilterGroup": "Add Filter Group",
"linkRecord": "Link record",
"addNewRecord": "Add new record",
"newRecord": "New record",
"tableNameCreateNewRecord": "{tableName}: Create new record",
"gotSavedLinkedSuccessfully": "{tableName} '{recordTitle}' got saved & linked successfully",
"recordCreatedLinked": "Record Created & Linked",
"useConnectionUrl": "Use Connection URL",
"toggleCommentsDraw": "Toggle comments draw",
"expandRecord": "Expand Record",
"deleteRecord": "Delete Record",
"fullWidth": "Full width",
"exitFullWidth": "Exit full width",
"markAllAsRead": "Mark all as read",
"column": {
"delete": "Delete Field",
"addNumber": "Add Number Field",
"addSingleLineText": "Add SingleLineText Field",
"addLongText": "Add LongText Field",
"addOther": "Add Other Field"
},
"erd": {
"showColumns": "Show Columns",
"showPkAndFk": "Show Primary and Foreign Keys",
@ -475,9 +853,11 @@
"openInGoogleMaps": "Google Maps",
"openInOpenStreetMap": "OSM"
},
"toggleMobileMode": "Toggle Mobile Mode"
"toggleMobileMode": "Toggle Mobile Mode",
"startCommenting": "Start commenting!"
},
"tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment",
"saveChanges": "Save changes",
"xcDB": "Create a new project",
"extDB": "Supports MySQL, PostgreSQL, SQL Server & SQLite",
@ -488,6 +868,7 @@
"light": "Does it come in Black ? (^⇧B)"
},
"addTable": "Add new table",
"addDashboard": "Add new Dashboard",
"inviteMore": "Invite more users",
"toggleNavDraw": "Toggle navigation drawer",
"reloadApiToken": "Reload API tokens",
@ -506,7 +887,19 @@
"clientCA": "Select CA file"
},
"placeholder": {
"selectSlackChannels": "Select Slack channels",
"selectTeamsChannels": "Select Microsoft Teams channels",
"selectDiscordChannels": "Select Discord channels",
"selectMattermostChannels": "Select Mattermost channels",
"webhookTitle": "Webhook Title",
"barcodeColumn": "Select a field for the Barcode value",
"notFoundContent": "No valid field Type can be found.",
"selectBarcodeFormat": "Select a Barcode format",
"projName": "Enter Project Name",
"selectGroupField": "Select a Grouping Field",
"selectGroupFieldNotFound": "No Single Select Field can be found. Please create one first.",
"selectGeoField": "Select a GeoData Field",
"selectGeoFieldNotFound": "No GeoData Field can be found. Please create one first.",
"password": {
"enter": "Enter the password",
"current": "Current password",
@ -514,6 +907,8 @@
"save": "Save password",
"confirm": "Confirm new password"
},
"selectAColumnForTheQRCodeValue": "Select a field for the QR code value",
"allowNegativeNumbers": "Allow negative numbers",
"searchProjectTree": "Search tables",
"searchFields": "Search fields",
"searchColumn": "Search {search} column",
@ -523,19 +918,137 @@
"defaultValue": "Default value",
"filterByEmail": "Filter by E-mail",
"filterQuery": "Filter query",
"selectField": "Select field"
"selectField": "Select field",
"precision": "Precision",
"decimal1": "1.0",
"decimal2": "1.00",
"decimal3": "1.000",
"decimal4": "1.0000",
"decimal5": "1.00000",
"decimal6": "1.000000",
"decimal7": "1.0000000",
"decimal8": "1.00000000",
"value": "Value",
"key": "Key"
},
"msg": {
"clickToCopyFieldId": "Click to copy Field Id",
"enterPassword": "Enter password",
"bySigningUp": "By signing up, you agree to the",
"subscribeToOurWeeklyNewsletter": "Subscribe to our weekly newsletter",
"verifyingPassword": "Verifying Password",
"thisSharedViewIsProtected": "This shared view is protected",
"successfullySubmittedFormData": "Successfully submitted form data",
"formViewNotSupportedOnMobile": "Form view is not supported on mobile",
"newFormWillBeLoaded": "New form will be loaded after {seconds} seconds",
"optimizedQueryDisabled": "Optimized query is disabled",
"optimizedQueryEnabled": "Optimized query is enabled",
"lookupNonBtWarning": "Lookup field is not supported for non-Belongs to relation",
"invalidTime": "Invalid Time",
"linkColumnClearNotSupportedYet": "You don't have any supported links for Lookup",
"recordCouldNotBeFound": "Record could not be found",
"invalidPhoneNumber": "Invalid phone number",
"pageSizeChanged": "Page size changed",
"errorLoadingData": "Error loading data",
"webhookBodyMsg1": "Use context variable",
"webhookBodyMsg2": "body",
"webhookBodyMsg3": "to refer the record under consideration",
"formula": {
"hintStart": "Hint: Use {placeholder1} to reference fields, e.g: {placeholder2}. For more, please check out",
"hintEnd": "Formulas.",
"noSuggestedFormulaFound": "No suggested formula found",
"numericTypeIsExpected": "Numeric type is expected",
"stringTypeIsExpected": "String type is expected",
"operationNotAvailable": "{operation} operation not available",
"cantSaveFieldFormulaInvalid": "Can’t save field because formula is invalid",
"notSupportedToReferenceColumn": "Not supported to reference field {columnName}",
"typeIsExpectedButFound": "Type {type} is expected but found Type {found}",
"requiredArgumentsFormula": "{calleeName} requires {requiredArguments} arguments",
"minRequiredArgumentsFormula": "{calleeName} required minimum {minRequiredArguments} arguments",
"maxRequiredArgumentsFormula": "{calleeName} required maximum {maxRequiredArguments} arguments",
"functionNotAvailable": "{function} function is not available",
"firstParamWeekDayHaveDate": "The first parameter of WEEKDAY() should have date value",
"secondParamWeekDayHaveDate": "The second parameter of WEEKDAY() should have the value either \"sunday\", \"monday\", \"tuesday\", \"wednesday\", \"thursday\", \"friday\" or \"saturday\"",
"firstParamDateAddHaveDate": "The first parameter of DATEADD() should have date value",
"secondParamDateAddHaveNumber": "The second parameter of DATEADD() should have numeric value",
"thirdParamDateAddHaveDate": "The third parameter of DATEADD() should have the value either \"day\", \"week\", \"month\" or \"year\"",
"firstParamDateDiffHaveDate": "The first parameter of DATEDIFF() should have date value",
"secondParamDateDiffHaveDate": "The second parameter of DATEDIFF() should have date value",
"thirdParamDateDiffHaveDate": "The third parameter of DATETIME_DIFF() should have value either \"milliseconds\", \"ms\", \"seconds\", \"s\", \"minutes\", \"m\", \"hours\", \"h\", \"days\", \"d\", \"weeks\", \"w\", \"months\", \"M\", \"quarters\", \"Q\", \"years\", or \"y\"",
"columnNotAvailable": "Field {columnName} is not available",
"cantSaveCircularReference": "Can’t save field because it causes a circular reference",
"columnWithTypeFoundButExpected": "Field {columnName} with {columnType} type is found but {expectedType} type is expected",
"columnNotMatchedWithType": "{columnName} is not matched with {columnType}"
},
"selectOption": {
"cantBeNull": "Select options can't be null",
"multiSelectCantHaveCommas": "MultiSelect fields can't have commas(',')",
"cantHaveDuplicates": "Select options can't have duplicates",
"createNewOptionNamed": "Create new option named"
},
"plsEnterANumber": "Please enter a number",
"plsInputEmail": "Please input email",
"invalidDate": "Invalid date",
"invalidLocale": "Invalid locale",
"invalidCurrencyCode": "Invalid Currency Code",
"postgresHasItsOwnCurrencySettings": "PostgreSQL 'money' type has own currency settings",
"validColumnsForBarCode": "The valid Field Types for a Barcode Field are: Number, Single Line Text, Long Text, Phone Number, URL, Email, Decimal. Please create one first.",
"hm": {
"title": "Has Many Relation",
"tooltip_desc": "A single record from table ",
"tooltip_desc2": " can be linked with multiple records from table "
},
"mm": {
"title": "Many to Many Relation",
"tooltip_desc": "Multiple records from table ",
"tooltip_desc2": " can be linked with multiple records from table "
},
"bt": {
"title": "Belongs to Relation",
"tooltip_desc": "A single record from table ",
"tooltip_desc2": " can be linked with a record from table "
},
"oo": {
"title": "One to One Relation",
"tooltip_desc": "A single record from table ",
"tooltip_desc2": " can be linked with a single record from table "
},
"noRecordsAreLinkedFromTable": "No records are linked from table",
"noRecordsLinked": "No records linked",
"recordsLinked": "records linked",
"acceptOnlyValid": "Accepts only",
"apiTokenCreate": "Create personal API tokens to use in automation or external apps.",
"selectFieldToSort": "Select Field to Sort",
"thereAreNoRecordsInTable": "There are no records in table",
"createWebhookMsg1": "Get started with web-hooks!",
"createWebhookMsg2": "Create web-hooks to power you automations,",
"createWebhookMsg3": "Get notified as soon as there are changes in your data",
"areYouSureUWantTo": "Are you sure you want to delete the following",
"areYouSureUWantToDeleteLabel": "Are you sure you want to {deleteLabel} the following",
"idColumnRequired": "ID field is required, you can rename this later if required.",
"length59Required": "The length exceeds the max 59 characters",
"noNewNotifications": "You have no new notifications",
"noRecordFound": "Record not found",
"rowDeleted": "Record deleted",
"saveChanges": "Do you want to save the changes?",
"tooLargeFieldEntity": "The field is too large to be converted to {entity}",
"roleRequired": "Role required",
"warning": {
"dbValid": "Please make sure database you are trying to connect is valid! This operation can cause schema loss!!",
"barcode": {
"renderError": "Barcode error - please check compatibility between input and barcode type"
},
"nonEditableFields": {
"computedFieldUnableToClear": "Warning: Computed field - unable to clear text",
"qrFieldsCannotBeDirectlyChanged": "Warning: QR fields cannot be directly changed."
}
"qrFieldsCannotBeDirectlyChanged": "Warning: QR fields cannot be directly changed.",
"barcodeFieldsCannotBeDirectlyChanged": "Warning: Barcode fields cannot be directly changed."
},
"duplicateProject": "Are you sure you want to duplicate the base?",
"duplicateTable": "Are you sure you want to duplicate the table?"
},
"info": {
"disabledAsViewLocked": "Disabled as View is locked",
"basesMigrated": "Bases are migrated. Please try again.",
"pasteNotSupported": "Paste operation is not supported on the active cell",
"roles": {
"orgCreator": "Creator can create new projects and access any invited project.",
@ -640,6 +1153,9 @@
"tablesMetadataInSync": "Tables metadata is in Sync",
"addMultipleUsers": "You can add multiple comma(,) separated emails",
"enterTableName": "Enter table name",
"enterLayoutName": "Enter Layout name",
"enterDashboardName": "Enter Dashboard name",
"defaultColumns": "Default fields",
"addDefaultColumns": "Add default columns",
"tableNameInDb": "Table name as saved in database",
"airtable": {
@ -662,8 +1178,10 @@
"valueAlreadyInList": "This value is already in the list",
"noColumnsToUpdate": "No columns to update",
"tableDeleted": "Deleted table successfully",
"layoutDeleted": "Deleted layout successfully",
"generatePublicShareableReadonlyBase": "Generate publicly shareable readonly base",
"deleteViewConfirmation": "Are you sure you want to delete this view?",
"deleteLayoutConfirmation": "Are you sure you want to delete this Layout?",
"deleteTableConfirmation": "Do you want to delete the table",
"showM2mTables": "Show M2M Tables",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
@ -674,18 +1192,40 @@
"deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",
"noMoreRecords": "No more records"
"noMoreRecords": "No more records",
"tokenNameNotEmpty": "Token name should not be empty",
"tokenNameMaxLength": "Token name should not be more than 255 characters",
"dbNameRequired": "Database name is required",
"wsNameRequired": "Workspace name required",
"wsNameMinLength": "Workspace name must be at least 3 characters long",
"wsNameMaxLength": "Workspace name must be at most 50 characters long",
"wsDeleteDlg": "Delete this workspace and all it’s contents.",
"userConfirmation": "I understand that this action is irreversible",
"pageNotFound": "Page Not Found",
"makeLineBreak": "to make a line break",
"goToPrevious": "Go to previous",
"goToNext": "Go to next",
"thankYou": "Thank you!",
"submittedFormData": "You have successfully submitted the form data."
},
"error": {
"nameRequired": "Name Required",
"nameMinLength": "Name must be at least 2 characters long",
"nameMaxLength": "Name must be at most 60 characters long",
"viewNameRequired": "View name is required",
"nameMaxLength256": "Name must be at most 256 characters long",
"viewNameUnique": "View name should be unique",
"searchProject": "Your search for {search} found no results",
"invalidChar": "Invalid character in folder path.",
"invalidDbCredentials": "Invalid database credentials.",
"unableToConnectToDb": "Unable to connect to database, please check your database is up.",
"invalidYear": "Invalid year",
"userDoesntHaveSufficientPermission": "User does not exist or have sufficient permission to create schema.",
"dbConnectionStatus": "Invalid database parameters",
"dbConnectionFailed": "Connection Failure:",
"nullFilterExists": "Null filter exists. Please remove them",
"signUpRules": {
"emailReqd": "E-mail is required",
"emailRequired": "Email is required",
"emailInvalid": "E-mail must be valid",
"passwdRequired": "Password is required",
"passwdLength": "You password must be atleast 8 characters",
@ -695,7 +1235,9 @@
"atLeastOneUppercase": "One Uppercase letter",
"atLeastOneNumber": "One Number",
"atLeastOneSpecialChar": "One special character",
"allowedSpecialCharList": "Allowed special character list"
"allowedSpecialCharList": "Allowed special character list",
"invalidEmails": "Invalid emails",
"invalidEmail": "Invalid Email"
},
"invalidURL": "Invalid URL",
"invalidEmail": "Invalid Email",
@ -726,6 +1268,8 @@
"nameShouldStartWithAnAlphabetOr_": "Name should start with an alphabet or _",
"followingCharactersAreNotAllowed": "Following characters are not allowed",
"columnNameRequired": "Column name is required",
"duplicateColumnName": "Duplicate field name",
"uiDataTypeRequired": "UI data type is required",
"columnNameExceedsCharacters": "The length of column name exceeds the max {value} characters",
"projectNameExceeds50Characters": "Project name exceeds 50 characters",
"projectNameCannotStartWithSpace": "Project name cannot start with space",
@ -758,6 +1302,7 @@
"futureRelease": "Coming soon!"
},
"success": {
"licenseKeyUpdated": "License Key Updated",
"columnDuplicated": "Column duplicated successfully",
"rowDuplicatedWithoutSavedYet": "Row duplicated (not saved)",
"updatedUIACL": "Updated UI ACL for tables successfully",
@ -765,6 +1310,7 @@
"pluginSettingsSaved": "Plugin settings saved successfully",
"pluginTested": "Successfully tested plugin settings",
"tableRenamed": "Table renamed successfully",
"layoutRenamed": "Layout renamed successfully",
"viewDeleted": "View deleted successfully",
"primaryColumnUpdated": "Successfully updated as primary column",
"tableDataExported": "Successfully exported all table data",

718
packages/nc-gui/lang/fa.json

File diff suppressed because it is too large Load Diff

580
packages/nc-gui/lang/fi.json

@ -1,5 +1,45 @@
{
"dashboards": {
"create_new_dashboard_project": "Create New Interface",
"connect_data_sources": "Connect data sources",
"alert": "Alert",
"alert-message": "No databases have been connected. Connect database bases to build interfaces. Skip this step and add databases from the base home page later.",
"select_database_projects_that_you_want_to_link_to_this_dashboard_projects": "Select Database Bases that you want to link to this Interface.",
"create_interface": "Create interface",
"project_name": "Base Name",
"connect": "Connect",
"buttonActionTypes": {
"open_external_url": "Open external link",
"delete_record": "Delete record",
"update_record": "Update record",
"open_layout": "Open layout"
},
"widgets": {
"static_text": "Text",
"chart": "Chart",
"table": "Table",
"image": "Image",
"map": "Map",
"button": "Button",
"number": "Number",
"bar_chart": "Bar Chart",
"line_chart": "Line Chart",
"area_chart": "Area Chart",
"pie_chart": "Pie Chart",
"donut_chart": "Donut Chart",
"scatter_plot": "Scatter Plot",
"bubble_chart": "Bubble Chart",
"radar_chart": "Radar Chart",
"polar_area_chart": "Polar Area Chart",
"radial_bar_chart": "Radial Bar Chart",
"heatmap_chart": "Heatmap Chart",
"treemap_chart": "Treemap Chart",
"box_plot_chart": "Box Plot Chart",
"candlestick_chart": "Candlestick Chart"
}
},
"general": {
"quit": "Quit",
"home": "Koti",
"load": "Ladata",
"open": "Avata",
@ -7,27 +47,67 @@
"yes": "Joo",
"no": "Ei",
"ok": "Ok",
"back": "Back",
"and": "Ja",
"or": "Tai",
"add": "Lisätä",
"edit": "Muokata",
"link": "Link",
"links": "Links",
"remove": "Poista",
"import": "Import",
"logout": "Log Out",
"empty": "Empty",
"changeIcon": "Change Icon",
"save": "Tallentaa",
"available": "Available",
"abort": "Abort",
"saving": "Saving",
"cancel": "Peruuttaa",
"null": "Null",
"escape": "Escape",
"hex": "Hex",
"clear": "Clear",
"slack": "Slack",
"comment": "Comment",
"microsoftTeams": "Microsoft Teams",
"discord": "Discord",
"matterMost": "Mattermost",
"twilio": "Twilio",
"whatsappTwilio": "WhatsApp Twilio",
"quote": "Quote",
"submit": "Lähetä",
"create": "Luoda",
"createEntity": "Create {entity}",
"creating": "Creating",
"creatingEntity": "Creating {entity}",
"details": "Details",
"skip": "Skip",
"code": "Code",
"duplicate": "Duplikaatti",
"duplicating": "Duplicating",
"activate": "Activate",
"action": "Action",
"insert": "Lisäys",
"delete": "Poistaa",
"deleteEntity": "Delete {entity}",
"bulkInsert": "Bulk Insert",
"bulkDelete": "Bulk Delete",
"bulkUpdate": "Bulk Update",
"deleting": "Deleting",
"update": "Päivittää",
"rename": "Nimeä uudelleen",
"reload": "Lataa uudelleen",
"reset": "Nollata",
"install": "Asentaa",
"show": "Näytä",
"access": "Access",
"visibility": "Visibility",
"hide": "Piilottaa",
"deprecated": "Deprecated",
"showAll": "Näytä kaikki",
"hideAll": "Piilota kaikki",
"notFound": "Not found",
"showMore": "Näytä lisää",
"showOptions": "Näytä vaihtoehdot",
"hideOptions": "Piilota vaihtoehtoja",
@ -47,6 +127,8 @@
"upload": "Ladata",
"download": "ladata",
"default": "Oletusarvo",
"base": "Source",
"datasource": "Data Source",
"more": "Lisää",
"less": "Vähemmän",
"event": "Tapahtuma",
@ -54,12 +136,14 @@
"after": "Jälkeen",
"before": "Ennen",
"search": "Hae",
"searchIn": "Search In",
"notification": "Ilmoitus",
"reference": "Viite",
"function": "Toiminto",
"confirm": "Vahvista",
"generate": "Luo",
"copy": "Kopioi",
"are": "are",
"misc": "Sekalaiset",
"lock": "Lukitus",
"unlock": "Avaa",
@ -76,9 +160,39 @@
"hideField": "Piilota kenttä",
"sortAsc": "Lajittelu nouseva",
"sortDesc": "Lajittelu laskeva",
"geoDataField": "GeoData Field"
"move": "Move",
"geoDataField": "GeoData Field",
"type": "Type",
"name": "Name",
"changes": "Changes",
"new": "New",
"old": "Old",
"data": "Data",
"source": "Source",
"destination": "Destination",
"active": "Active",
"inactive": "Inactive",
"linked": "linked",
"finish": "Finish",
"min": "Min",
"max": "Max",
"avg": "Avg",
"sum": "Sum",
"count": "Count",
"countDistinct": "Count Distinct",
"sumDistinct": "Sum Distinct",
"avgDistinct": "Avg Distinct",
"join": "Join",
"options": "Options",
"primaryValue": "Primary Value",
"useSurveyMode": "Use Survey Mode",
"shift": "Shift",
"enter": "Enter",
"seconds": "Seconds"
},
"objects": {
"workspace": "Workspace",
"workspaces": "Workspaces",
"project": "Hanke",
"projects": "Hankkeet",
"table": "Pöytä",
@ -95,6 +209,7 @@
"webhooks": "Verkkokoukut",
"view": "Näkymä",
"views": "Näkymät",
"sidebar": "Sidebar",
"viewType": {
"grid": "Ruudukko",
"gallery": "Galleria",
@ -107,16 +222,27 @@
"users": "Käyttäjät",
"role": "Rooli",
"roles": "Roolit",
"developer": "Developer",
"roleType": {
"owner": "Omistaja",
"creator": "Luoja",
"editor": "Toimittaja",
"commenter": "Kommentti",
"viewer": "Katselija",
"noaccess": "No Access",
"superAdmin": "Super Admin",
"orgLevelCreator": "Organisaatiotason luoja",
"orgLevelViewer": "Organisaatiotason katseluohjelma"
},
"sqlVIew": "SQL-näkymä"
"sqlVIew": "SQL-näkymä",
"rowHeight": "Record Height",
"heightClass": {
"short": "Short",
"medium": "Medium",
"tall": "Tall",
"extra": "Extra"
},
"externalDb": "External Database"
},
"datatype": {
"ID": "Id",
@ -171,17 +297,63 @@
"isNotNull": "ei ole nolla"
},
"title": {
"docs": "Docs",
"forum": "Forum",
"parameter": "Parameter",
"headers": "Headers",
"parameterName": "Parameter Name",
"currencyLocale": "Currency Locale",
"currencyCode": "Currency Code",
"searchMembers": "Search Members",
"noMembersFound": "No members found",
"dateJoined": "Date Joined",
"tokenName": "Token name",
"inDesktop": "in Desktop",
"rowData": "Record data",
"creator": "Creator",
"qrCode": "QR Code",
"termsOfService": "Terms of Service",
"updateSelectedRows": "Update Selected Records",
"noFiltersAdded": "No filters added",
"editCards": "Edit Cards",
"noFieldsFound": "No fields found",
"displayValue": "Display Value",
"expand": "Expand",
"hideAll": "Hide all",
"hideSystemFields": "Hide system fields",
"removeFile": "Remove File",
"hasMany": "Has Many",
"manyToMany": "Many to Many",
"virtualRelation": "Virtual Relation",
"linkMore": "Link More",
"linkMoreRecords": "Link more records",
"downloadFile": "Download File",
"renameTable": "Rename Table",
"renamingTable": "Renaming Table",
"renamingWs": "Renaming Workspace",
"renameWs": "Rename Workspace",
"deleteWs": "Delete Workspace",
"deletingWs": "Deleting Workspace",
"copyAuthToken": "Copy Auth Token",
"copiedAuthToken": "Copied Auth Token",
"copyInviteToken": "Copy Invite Token",
"showSidebar": "Show Sidebar",
"hideSidebar": "Hide Sidebar",
"creatingTable": "Creating Table",
"erdView": "ERD-näkymä",
"newBase": "New Data Source",
"newProj": "Uusi projekti",
"createBase": "Create Base",
"myProject": "Omat hankkeet",
"formTitle": "Muodosta otsikko",
"collabView": "Yhteistyökuvaus",
"lockedView": "Lukittu näkymä",
"personalView": "Henkilökohtainen näkymä",
"collaborative": "Collaborative",
"locked": "Locked",
"personal": "Personal",
"appStore": "Sovelluskauppa",
"teamAndAuth": "Joukkue & valtuutus",
"rolesUserMgmt": "Roolit ja käyttäjien hallinta",
"userMgmt": "Käyttäjien hallinta",
"apiTokens": "API Tokens",
"apiTokenMgmt": "API Tokensin hallinta",
"rolesMgmt": "Roolit hallinta",
"projMeta": "Hankkeen metatiedot",
@ -204,20 +376,129 @@
"generateToken": "Luo tunniste",
"APIsAndSupport": "API:t ja tuki",
"helpCenter": "Ohjekeskus",
"noLabels": "No Labels",
"swaggerDocumentation": "Swaggerin dokumentaatio",
"quickImportFrom": "Nopea tuonti",
"quickImport": "Pikatuonti",
"quickImportAirtable": "Quick Import - Airtable",
"quickImportCSV": "Quick Import - CSV",
"quickImportExcel": "Quick Import - Excel",
"quickImportJSON": "Quick Import - JSON",
"jsonEditor": "JSON Editor",
"comingSoon": "Coming Soon",
"advancedSettings": "Lisäasetukset",
"codeSnippet": "Koodinpätkä",
"keyboardShortcut": "Näppäimistön pikanäppäimet",
"generateRandomName": "Generate Random Name",
"findRowByScanningCode": "Find row by scanning a QR or Barcode"
"findRowByScanningCode": "Find row by scanning a QR or Barcode",
"tokenManagement": "Token Management",
"addNewToken": "Add new token",
"accountSettings": "Account Settings",
"resetPasswordMenu": "Reset Password",
"tokens": "Tokens",
"userManagement": "User Management",
"accountManagement": "Account management",
"licence": "Licence",
"allowAllMimeTypes": "Allow All Mime Types",
"defaultView": "Default View",
"relations": "Relations",
"switchLanguage": "Switch Language",
"renameFile": "Rename File",
"links": {
"noAction": "No Action",
"cascade": "Cascade",
"restrict": "Restrict",
"setNull": "Set NULL",
"setDefault": "Set Default"
}
},
"labels": {
"heading1": "Heading 1",
"heading2": "Heading 2",
"heading3": "Heading 3",
"bold": "Bold",
"italic": "Italic",
"underline": "Underline",
"strike": "Strike",
"taskList": "Task List",
"bulletList": "Bullet List",
"numberedList": "Numbered List",
"downloadData": "Download Data",
"blockQuote": "Block Quote",
"noToken": "No Token",
"tokenLimit": "Only one token per user is allowed",
"duplicateAttachment": "File with name {filename} already attached",
"viewIdColon": "VIEW ID: {viewId}",
"toAddress": "To Address",
"subject": "Subject",
"body": "Body",
"commaSeparatedMobileNumber": "Comma separated Mobile #",
"headerName": "Header Name",
"icon": "Icon",
"max": "Max",
"enableRichText": "Enable Rich Text",
"idColon": "Id:",
"copiedRecordURL": "Copied Record URL",
"copyRecordURL": "Copy Record URL",
"duplicateRecord": "Duplicate record",
"binaryEncodingFormat": "Binary encoding format",
"syntax": "Syntax",
"examples": "Examples",
"durationInfo": "A duration of time in minutes or seconds (e.g. 1:23).",
"addHeader": "Add Header",
"enterDefaultUrlOptional": "Enter default URL (Optional)",
"negative": "Negative",
"discard": "Discard",
"default": "Default",
"defaultNumberPercent": "Default Number (%)",
"durationFormat": "Duration Format",
"dateFormat": "Date Format",
"timeFormat": "Time Format",
"singularLabel": "Singular Label",
"pluralLabel": "Plural Label",
"optional": "(Optional)",
"clickToMake": "Click to make",
"visibleForRole": "visible for role:",
"inUI": "in UI Dashboard",
"projectSettings": "Base Settings",
"clickToHide": "Click to hide",
"clickToDownload": "Click to download",
"forRole": "for role",
"clickToCopyViewID": "Click to copy View ID",
"viewMode": "View Mode",
"searchUsers": "Search Users",
"superAdmin": "Super Admin",
"allTables": "All Tables",
"members": "Members",
"dataSources": "Data Sources",
"connectDataSource": "Connect a Data Source",
"searchProjects": "Search Bases",
"createdBy": "Luonut",
"viewingAttachmentsOf": "Viewing Attachments of",
"readOnly": "Readonly",
"dropHere": "Drop here",
"createdOn": "Created On",
"notifyVia": "Ilmoittaa kautta",
"projName": "Projektin nimi",
"profile": "Profile",
"accountDetails": "Account Details",
"controlAppearance": "Control your Appearance.",
"accountEmailID": "Account Email ID",
"backToWorkspace": "Back to Workspace",
"untitledToken": "Untitled token",
"tableName": "Taulukon nimi",
"dashboardName": "Dashboard name",
"createView": "Create a View",
"creatingView": "Creating View",
"duplicateView": "Duplicate View",
"duplicateGridView": "Duplicate Grid View",
"createGridView": "Create Grid View",
"duplicateGalleryView": "Duplicate Gallery View",
"createGalleryView": "Create Gallery View",
"duplicateFormView": "Duplicate Form View",
"createFormView": "Create Form View",
"duplicateKanbanView": "Duplicate Kanban View",
"createKanbanView": "Create Kanban View",
"viewName": "Näytä nimi",
"viewLink": "Näytä linkki",
"columnName": "Sarakkeen nimi",
@ -247,6 +528,14 @@
"where": "Missä",
"cache": "Kätkö",
"chat": "Keskustella",
"showOrHide": "Show or Hide",
"airtable": "Airtable",
"csv": "CSV",
"csvFile": "CSV File",
"json": "JSON",
"jsonFile": "JSON File",
"excel": "Excel",
"microsoftExcel": "Microsoft Excel",
"email": "Sähköposti",
"storage": "Varastointi",
"uiAcl": "UI-ACL",
@ -255,6 +544,7 @@
"created": "Luotu",
"sqlOutput": "SQL-lähtö",
"addOption": "Lisää vaihtoehto",
"interfaceColor": "Interface Color",
"qrCodeValueColumn": "Sarake, jossa on QR-koodin arvo",
"barcodeValueColumn": "Sarake, jossa on viivakoodin arvo",
"barcodeFormat": "Viivakoodin muoto",
@ -282,13 +572,17 @@
"joinDiscord": "Liity discordiin",
"joinCommunity": "Liity NocoDB-yhteisöön",
"joinReddit": "Liity /r/NocoDB",
"followNocodb": "Seuraa NocoDB"
"followNocodb": "Seuraa NocoDB",
"communityTranslated": "(Community Translated)"
},
"twitter": "Twitter",
"docReference": "Asiakirjan viite",
"selectUserRole": "Valitse käyttäjän rooli",
"childTable": "Lapsipöytä",
"childColumn": "Lapsipylväs",
"childField": "Child field",
"linkToAnotherRecord": "Linkki toiseen tietueeseen",
"links": "Links",
"onUpdate": "Päivitys",
"onDelete": "Poista",
"account": "Tili",
@ -298,16 +592,21 @@
"customTheme": "Mukautettu teema",
"requestDataSource": "Pyydätkö tarvitsemaasi tietolähdettä?",
"apiKey": "API-avain",
"sharedBase": "Jaettu tukikohta",
"personalAccessToken": "Personal Access Token",
"sharedBaseUrl": "Shared Base URL",
"importData": "Tuo tietoja",
"importSecondaryViews": "Toissijaisten näkymien tuonti",
"importRollupColumns": "Rollup-sarakkeiden tuonti",
"importLookupColumns": "Tuo hakusarakkeita",
"importAttachmentColumns": "Liitesarakkeiden tuominen",
"importFormulaColumns": "Tuo kaavan sarakkeet",
"importUsers": "Import Users (by email)",
"noData": "Ei tietoja",
"goToDashboard": "Siirry kojelautaan",
"importing": "Tuo",
"formatJson": "Format JSON",
"autoSelectFieldTypes": "Auto-Select Field Types",
"firstRowAsHeaders": "Use First Record as Headers",
"flattenNested": "Flatten Nested",
"downloadAllowed": "Lataa sallittu",
"weAreHiring": "Me palkkaamme!",
@ -325,9 +624,61 @@
"welcomeToNc": "Tervetuloa NocoDB:hen!",
"inviteOnlySignup": "Salli rekisteröityminen vain kutsun url-osoitteen avulla",
"nextRow": "Seuraava rivi",
"prevRow": "Edellinen rivi"
"prevRow": "Edellinen rivi",
"addRowGrid": "Manually add data in grid view",
"addRowForm": "Enter record data through a form",
"noAccess": "No access",
"restApis": "Rest APIs",
"apis": "APIs",
"includeData": "Include Data",
"includeView": "Include View",
"includeWebhook": "Include Webhook",
"zoomInToViewColumns": "Zoom in to view columns",
"embedInSite": "Embed this view in your site",
"titleRequired": "title is required.",
"sourceNameRequired": "Source name is required",
"changeWsName": "Change Workspace Name",
"pressEnter": "Press Enter",
"newFormLoaded": "New form will be loaded after"
},
"activity": {
"openInANewTab": "Open in a new tab",
"copyIFrameCode": "Copy IFrame code",
"onCondition": "On Condition",
"bulkDownload": "Bulk Download",
"attachFile": "Attach File",
"viewAttachment": "View Attachments",
"attachmentDrop": "Click or drop a file into cell",
"addFiles": "Add File(s)",
"hideInUI": "Hide in UI",
"addBase": "Add Base",
"addParameter": "Add Parameter",
"submitAnotherForm": "Submit Another Form",
"dragAndDropFieldsHereToAdd": "Drag and drop fields here to add",
"editSource": "Edit Data Source",
"enterText": "Enter text",
"okEditBase": "Ok & Edit Base",
"showInUI": "Show in UI",
"outOfSync": "Out of sync",
"newSource": "New Data Source",
"newWebhook": "New Webhook",
"enablePublicAccess": "Enable Public Access",
"doYouWantToSaveTheChanges": "Do you want to save the changes ?",
"editingAccess": "Editing access",
"enabledPublicViewing": "Enable public viewing",
"restrictAccessWithPassword": "Restrict access with password",
"manageProjectAccess": "Manage Base Access",
"allowDownload": "Allow Download",
"surveyMode": "Survey Mode",
"rtlOrientation": "RTL Orientation",
"useTheme": "Use Theme",
"copyLink": "Copy Link",
"copiedLink": "Link Copied",
"copyInviteLink": "Copy invite link",
"copiedInviteLink": "Copied invite link",
"copyUrl": "Kopioi URL-osoite",
"moreColors": "More Colors",
"moveProject": "Move Base",
"createProject": "Luo projekti",
"importProject": "Tuontihanke",
"searchProject": "Hakuprojekti",
@ -338,6 +689,7 @@
"deleteProject": "Poista projekti",
"refreshProject": "Päivitä projekteja",
"saveProject": "Tallenna projekti",
"saveAndQuit": "Save & Quit",
"deleteKanbanStack": "Poista pino?",
"createProjectExtended": {
"extDB": "Luo liittämällä <br> ulkoiseen tietokantaan",
@ -353,6 +705,7 @@
"translate": "Ohje Käännä",
"account": {
"authToken": "Kopioi Auth Token",
"authTokenCopied": "Copied Auth Token",
"swagger": "Swagger: REST API:t",
"projInfo": "Kopioi projektitiedot",
"themes": "Teemat"
@ -362,7 +715,10 @@
"filter": "Suodattaa",
"addFilter": "Lisää suodatin",
"share": "Jaa",
"groupBy": "Group By",
"addSubGroup": "Add subgroup",
"shareBase": {
"label": "Share base",
"disable": "Poista jaettu pohja",
"enable": "Jokainen, jolla on linkki",
"link": "Jaettu peruslinkki"
@ -372,6 +728,8 @@
"inviteTeam": "Kutsu tiimi",
"inviteUser": "Kutsu käyttäjä",
"inviteToken": "Kutsua token",
"linkedRecords": "Linked Records",
"addNewLink": "Add New Link",
"newUser": "Uusi käyttäjä",
"editUser": "Muokkaa käyttäjää",
"deleteUser": "Poista käyttäjä projektista",
@ -386,8 +744,11 @@
"previousRecord": "Edellinen ennätys",
"copyApiURL": "Kopioi API URL",
"createTable": "Create New Table",
"createDashboard": "Create Dashboard",
"createWorkspace": "Create Workspace",
"refreshTable": "Taulukot päivitys",
"renameTable": "Rename Table",
"renameLayout": "Layout Rename",
"deleteTable": "Delete Table",
"addField": "Lisää uusi kenttä tähän taulukkoon",
"setDisplay": "Set as Display value",
@ -398,6 +759,9 @@
"insertRow": "Lisää uusi rivi",
"duplicateRow": "Duplicate Row",
"deleteRow": "Poista rivi",
"deleteRows": "Delete records",
"predictColumns": "Predict Fields",
"predictFormulas": "Predict Formulas",
"deleteSelectedRow": "Poista valitut rivit",
"importExcel": "Tuonti excel",
"importCSV": "Tuo CSV",
@ -418,6 +782,7 @@
"ListView": "Näkymät",
"copyView": "Kopionä näkymä",
"renameView": "Nimeä näkymä uudelleen",
"uploadData": "Upload Data",
"deleteView": "Poista näkymä",
"createGrid": "Luo verkkokuva",
"createGallery": "Luo gallerianäkymä",
@ -425,7 +790,6 @@
"createKanban": "Luo Kanban View",
"createForm": "Luo lomakkeenäkymä",
"showSystemFields": "Näytä järjestelmäkenttiä",
"copyUrl": "Kopioi URL-osoite",
"openTab": "Avaa uusi välilehti",
"iFrame": "Kopioi Embeddable HTML-koodi",
"addWebhook": "Lisää uusi webhotok",
@ -451,10 +815,24 @@
"addFilterGroup": "Lisää suodatinryhmä",
"linkRecord": "Linkkitietue",
"addNewRecord": "Lisää uusi tietue",
"newRecord": "New record",
"tableNameCreateNewRecord": "{tableName}: Create new record",
"gotSavedLinkedSuccessfully": "{tableName} '{recordTitle}' got saved & linked successfully",
"recordCreatedLinked": "Record Created & Linked",
"useConnectionUrl": "Käytä yhteys-URL:ää",
"toggleCommentsDraw": "Toggle kommentit piirtää",
"expandRecord": "Laajenna ennätys",
"deleteRecord": "Poista tietue",
"fullWidth": "Full width",
"exitFullWidth": "Exit full width",
"markAllAsRead": "Mark all as read",
"column": {
"delete": "Delete Field",
"addNumber": "Add Number Field",
"addSingleLineText": "Add SingleLineText Field",
"addLongText": "Add LongText Field",
"addOther": "Add Other Field"
},
"erd": {
"showColumns": "Näytä sarakkeet",
"showPkAndFk": "Näytä ensisijaiset ja vieraat avaimet",
@ -475,9 +853,11 @@
"openInGoogleMaps": "Google Maps",
"openInOpenStreetMap": "OSM"
},
"toggleMobileMode": "Toggle Mobile Mode"
"toggleMobileMode": "Toggle Mobile Mode",
"startCommenting": "Start commenting!"
},
"tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment",
"saveChanges": "Tallenna muutokset",
"xcDB": "Luo uusi projekti",
"extDB": "Tukee MySQL, PostgreSQL, SQL Server & Sqlite",
@ -488,6 +868,7 @@
"light": "Tuleeko se mustaksi? (^ ⇧b)"
},
"addTable": "Lisää uusi pöytä",
"addDashboard": "Add new Dashboard",
"inviteMore": "Kutsu lisää käyttäjiä",
"toggleNavDraw": "Vaihda navigaattori",
"reloadApiToken": "Lataa API-rahakkeet uudelleen",
@ -506,7 +887,19 @@
"clientCA": "Valitse CA-tiedosto"
},
"placeholder": {
"selectSlackChannels": "Select Slack channels",
"selectTeamsChannels": "Select Microsoft Teams channels",
"selectDiscordChannels": "Select Discord channels",
"selectMattermostChannels": "Select Mattermost channels",
"webhookTitle": "Webhook Title",
"barcodeColumn": "Select a field for the Barcode value",
"notFoundContent": "No valid field Type can be found.",
"selectBarcodeFormat": "Select a Barcode format",
"projName": "Anna projektin nimi",
"selectGroupField": "Select a Grouping Field",
"selectGroupFieldNotFound": "No Single Select Field can be found. Please create one first.",
"selectGeoField": "Select a GeoData Field",
"selectGeoFieldNotFound": "No GeoData Field can be found. Please create one first.",
"password": {
"enter": "Anna salasana",
"current": "Nykyinen salasana",
@ -514,6 +907,8 @@
"save": "Tallenna salasana",
"confirm": "Vahvista uusi salasana"
},
"selectAColumnForTheQRCodeValue": "Select a field for the QR code value",
"allowNegativeNumbers": "Allow negative numbers",
"searchProjectTree": "Hakupöydät",
"searchFields": "Hakukentät",
"searchColumn": "Hae {Haku} sarake",
@ -523,19 +918,137 @@
"defaultValue": "Oletusarvo",
"filterByEmail": "Suodata sähköpostitse",
"filterQuery": "Suodata kysely",
"selectField": "Valitse kenttä"
"selectField": "Valitse kenttä",
"precision": "Precision",
"decimal1": "1.0",
"decimal2": "1.00",
"decimal3": "1.000",
"decimal4": "1.0000",
"decimal5": "1.00000",
"decimal6": "1.000000",
"decimal7": "1.0000000",
"decimal8": "1.00000000",
"value": "Value",
"key": "Key"
},
"msg": {
"clickToCopyFieldId": "Click to copy Field Id",
"enterPassword": "Enter password",
"bySigningUp": "By signing up, you agree to the",
"subscribeToOurWeeklyNewsletter": "Subscribe to our weekly newsletter",
"verifyingPassword": "Verifying Password",
"thisSharedViewIsProtected": "This shared view is protected",
"successfullySubmittedFormData": "Successfully submitted form data",
"formViewNotSupportedOnMobile": "Form view is not supported on mobile",
"newFormWillBeLoaded": "New form will be loaded after {seconds} seconds",
"optimizedQueryDisabled": "Optimized query is disabled",
"optimizedQueryEnabled": "Optimized query is enabled",
"lookupNonBtWarning": "Lookup field is not supported for non-Belongs to relation",
"invalidTime": "Invalid Time",
"linkColumnClearNotSupportedYet": "You don't have any supported links for Lookup",
"recordCouldNotBeFound": "Record could not be found",
"invalidPhoneNumber": "Invalid phone number",
"pageSizeChanged": "Page size changed",
"errorLoadingData": "Error loading data",
"webhookBodyMsg1": "Use context variable",
"webhookBodyMsg2": "body",
"webhookBodyMsg3": "to refer the record under consideration",
"formula": {
"hintStart": "Hint: Use {placeholder1} to reference fields, e.g: {placeholder2}. For more, please check out",
"hintEnd": "Formulas.",
"noSuggestedFormulaFound": "No suggested formula found",
"numericTypeIsExpected": "Numeric type is expected",
"stringTypeIsExpected": "String type is expected",
"operationNotAvailable": "{operation} operation not available",
"cantSaveFieldFormulaInvalid": "Can’t save field because formula is invalid",
"notSupportedToReferenceColumn": "Not supported to reference field {columnName}",
"typeIsExpectedButFound": "Type {type} is expected but found Type {found}",
"requiredArgumentsFormula": "{calleeName} requires {requiredArguments} arguments",
"minRequiredArgumentsFormula": "{calleeName} required minimum {minRequiredArguments} arguments",
"maxRequiredArgumentsFormula": "{calleeName} required maximum {maxRequiredArguments} arguments",
"functionNotAvailable": "{function} function is not available",
"firstParamWeekDayHaveDate": "The first parameter of WEEKDAY() should have date value",
"secondParamWeekDayHaveDate": "The second parameter of WEEKDAY() should have the value either \"sunday\", \"monday\", \"tuesday\", \"wednesday\", \"thursday\", \"friday\" or \"saturday\"",
"firstParamDateAddHaveDate": "The first parameter of DATEADD() should have date value",
"secondParamDateAddHaveNumber": "The second parameter of DATEADD() should have numeric value",
"thirdParamDateAddHaveDate": "The third parameter of DATEADD() should have the value either \"day\", \"week\", \"month\" or \"year\"",
"firstParamDateDiffHaveDate": "The first parameter of DATEDIFF() should have date value",
"secondParamDateDiffHaveDate": "The second parameter of DATEDIFF() should have date value",
"thirdParamDateDiffHaveDate": "The third parameter of DATETIME_DIFF() should have value either \"milliseconds\", \"ms\", \"seconds\", \"s\", \"minutes\", \"m\", \"hours\", \"h\", \"days\", \"d\", \"weeks\", \"w\", \"months\", \"M\", \"quarters\", \"Q\", \"years\", or \"y\"",
"columnNotAvailable": "Field {columnName} is not available",
"cantSaveCircularReference": "Can’t save field because it causes a circular reference",
"columnWithTypeFoundButExpected": "Field {columnName} with {columnType} type is found but {expectedType} type is expected",
"columnNotMatchedWithType": "{columnName} is not matched with {columnType}"
},
"selectOption": {
"cantBeNull": "Select options can't be null",
"multiSelectCantHaveCommas": "MultiSelect fields can't have commas(',')",
"cantHaveDuplicates": "Select options can't have duplicates",
"createNewOptionNamed": "Create new option named"
},
"plsEnterANumber": "Please enter a number",
"plsInputEmail": "Please input email",
"invalidDate": "Invalid date",
"invalidLocale": "Invalid locale",
"invalidCurrencyCode": "Invalid Currency Code",
"postgresHasItsOwnCurrencySettings": "PostgreSQL 'money' type has own currency settings",
"validColumnsForBarCode": "The valid Field Types for a Barcode Field are: Number, Single Line Text, Long Text, Phone Number, URL, Email, Decimal. Please create one first.",
"hm": {
"title": "Has Many Relation",
"tooltip_desc": "A single record from table ",
"tooltip_desc2": " can be linked with multiple records from table "
},
"mm": {
"title": "Many to Many Relation",
"tooltip_desc": "Multiple records from table ",
"tooltip_desc2": " can be linked with multiple records from table "
},
"bt": {
"title": "Belongs to Relation",
"tooltip_desc": "A single record from table ",
"tooltip_desc2": " can be linked with a record from table "
},
"oo": {
"title": "One to One Relation",
"tooltip_desc": "A single record from table ",
"tooltip_desc2": " can be linked with a single record from table "
},
"noRecordsAreLinkedFromTable": "No records are linked from table",
"noRecordsLinked": "No records linked",
"recordsLinked": "records linked",
"acceptOnlyValid": "Accepts only",
"apiTokenCreate": "Create personal API tokens to use in automation or external apps.",
"selectFieldToSort": "Select Field to Sort",
"thereAreNoRecordsInTable": "There are no records in table",
"createWebhookMsg1": "Get started with web-hooks!",
"createWebhookMsg2": "Create web-hooks to power you automations,",
"createWebhookMsg3": "Get notified as soon as there are changes in your data",
"areYouSureUWantTo": "Are you sure you want to delete the following",
"areYouSureUWantToDeleteLabel": "Are you sure you want to {deleteLabel} the following",
"idColumnRequired": "ID field is required, you can rename this later if required.",
"length59Required": "The length exceeds the max 59 characters",
"noNewNotifications": "You have no new notifications",
"noRecordFound": "Record not found",
"rowDeleted": "Record deleted",
"saveChanges": "Do you want to save the changes?",
"tooLargeFieldEntity": "The field is too large to be converted to {entity}",
"roleRequired": "Role required",
"warning": {
"dbValid": "Please make sure database you are trying to connect is valid! This operation can cause schema loss!!",
"barcode": {
"renderError": "Viivakoodivirhe - tarkista syötteen ja viivakoodityypin yhteensopivuus."
},
"nonEditableFields": {
"computedFieldUnableToClear": "Varoitus: Laskettu kenttä - tekstiä ei voida tyhjentää",
"qrFieldsCannotBeDirectlyChanged": "Varoitus: QR-kenttiä ei voi suoraan muuttaa."
}
"qrFieldsCannotBeDirectlyChanged": "Varoitus: QR-kenttiä ei voi suoraan muuttaa.",
"barcodeFieldsCannotBeDirectlyChanged": "Warning: Barcode fields cannot be directly changed."
},
"duplicateProject": "Are you sure you want to duplicate the base?",
"duplicateTable": "Are you sure you want to duplicate the table?"
},
"info": {
"disabledAsViewLocked": "Disabled as View is locked",
"basesMigrated": "Bases are migrated. Please try again.",
"pasteNotSupported": "Liitä-toimintoa ei tueta aktiivisessa solussa.",
"roles": {
"orgCreator": "Luoja voi luoda uusia projekteja ja käyttää kaikkia kutsuttuja projekteja.",
@ -640,6 +1153,9 @@
"tablesMetadataInSync": "Taulukot Metatieto on synkronoitu",
"addMultipleUsers": "Voit lisätä useita pilkuja (,) erotettuja sähköposteja",
"enterTableName": "Anna taulukon nimi",
"enterLayoutName": "Enter Layout name",
"enterDashboardName": "Enter Dashboard name",
"defaultColumns": "Default fields",
"addDefaultColumns": "Lisää oletuspylväät",
"tableNameInDb": "Taulukon nimi tallennetaan tietokantaan",
"airtable": {
@ -662,8 +1178,10 @@
"valueAlreadyInList": "Tämä arvo on jo luettelossa",
"noColumnsToUpdate": "Ei päivitettäviä sarakkeita",
"tableDeleted": "Poistettu taulukko onnistuneesti",
"layoutDeleted": "Deleted layout successfully",
"generatePublicShareableReadonlyBase": "Luo julkisesti jaettavissa oleva lukukelpoinen pohja",
"deleteViewConfirmation": "Haluatko varmasti poistaa tämän näkymän?",
"deleteLayoutConfirmation": "Are you sure you want to delete this Layout?",
"deleteTableConfirmation": "Haluatko poistaa taulukon",
"showM2mTables": "Näytä M2M-taulukot",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
@ -674,18 +1192,40 @@
"deleteKanbanStackConfirmation": "Tämän pinon poistaminen poistaa myös valintavaihtoehdon `{stackToBeDeleted}` valikosta `{groupingField}`. Tietueet siirtyvät luokittelemattomaan pinoon.",
"computedFieldEditWarning": "Laskettu kenttä: sisältö on vain luettavissa. Käytä sarakkeen muokkausvalikkoa uudelleenmäärittämiseen",
"computedFieldDeleteWarning": "Laskettu kenttä: sisältö on vain luettavissa. Sisältöä ei voi tyhjentää.",
"noMoreRecords": "Ei enää tallenteita"
"noMoreRecords": "Ei enää tallenteita",
"tokenNameNotEmpty": "Token name should not be empty",
"tokenNameMaxLength": "Token name should not be more than 255 characters",
"dbNameRequired": "Database name is required",
"wsNameRequired": "Workspace name required",
"wsNameMinLength": "Workspace name must be at least 3 characters long",
"wsNameMaxLength": "Workspace name must be at most 50 characters long",
"wsDeleteDlg": "Delete this workspace and all it’s contents.",
"userConfirmation": "I understand that this action is irreversible",
"pageNotFound": "Page Not Found",
"makeLineBreak": "to make a line break",
"goToPrevious": "Go to previous",
"goToNext": "Go to next",
"thankYou": "Thank you!",
"submittedFormData": "You have successfully submitted the form data."
},
"error": {
"nameRequired": "Name Required",
"nameMinLength": "Name must be at least 2 characters long",
"nameMaxLength": "Name must be at most 60 characters long",
"viewNameRequired": "View name is required",
"nameMaxLength256": "Name must be at most 256 characters long",
"viewNameUnique": "View name should be unique",
"searchProject": "Hakusi {haku} ei löytänyt tuloksia",
"invalidChar": "Virheellinen merkki kansioreitillä.",
"invalidDbCredentials": "Virheelliset tietokannan tunnistetiedot.",
"unableToConnectToDb": "Tietokantaan ei voi muodostaa yhteyttä, tarkista tietokantaasi.",
"invalidYear": "Invalid year",
"userDoesntHaveSufficientPermission": "Käyttäjää ei ole olemassa tai jolla on riittävä lupa luoda kaavio.",
"dbConnectionStatus": "Virheelliset tietokannan parametrit",
"dbConnectionFailed": "Yhteys epäonnistuminen:",
"nullFilterExists": "Null filter exists. Please remove them",
"signUpRules": {
"emailReqd": "Sähköposti vaaditaan",
"emailRequired": "Email is required",
"emailInvalid": "Sähköpostin on oltava voimassa",
"passwdRequired": "salasana tarvitaan",
"passwdLength": "Salasanan on oltava vähintään 8 merkkiä",
@ -695,7 +1235,9 @@
"atLeastOneUppercase": "Yksi iso kirjain",
"atLeastOneNumber": "Yksi numero",
"atLeastOneSpecialChar": "Yksi erikoismerkki",
"allowedSpecialCharList": "Sallittujen erikoismerkkien luettelo"
"allowedSpecialCharList": "Sallittujen erikoismerkkien luettelo",
"invalidEmails": "Invalid emails",
"invalidEmail": "Invalid Email"
},
"invalidURL": "Virheellinen URL-osoite",
"invalidEmail": "Invalid Email",
@ -726,6 +1268,8 @@
"nameShouldStartWithAnAlphabetOr_": "Nimen on alettava aakkosilla tai _",
"followingCharactersAreNotAllowed": "Seuraavat merkit eivät ole sallittuja",
"columnNameRequired": "Sarakkeen nimi vaaditaan",
"duplicateColumnName": "Duplicate field name",
"uiDataTypeRequired": "UI data type is required",
"columnNameExceedsCharacters": "The length of column name exceeds the max {value} characters",
"projectNameExceeds50Characters": "Hankkeen nimi ylittää 50 merkkiä",
"projectNameCannotStartWithSpace": "Projektin nimi ei voi alkaa välilyönnillä",
@ -758,6 +1302,7 @@
"futureRelease": "Tulossa pian!"
},
"success": {
"licenseKeyUpdated": "License Key Updated",
"columnDuplicated": "Sarake monistettu onnistuneesti",
"rowDuplicatedWithoutSavedYet": "Row duplicated (not saved)",
"updatedUIACL": "Päivitetty UI ACL taulukoille onnistuneesti",
@ -765,6 +1310,7 @@
"pluginSettingsSaved": "Liitännäisen asetukset tallennettu onnistuneesti",
"pluginTested": "Onnistuneesti testattu plugin asetukset",
"tableRenamed": "Taulukko nimetty uudelleen onnistuneesti",
"layoutRenamed": "Layout renamed successfully",
"viewDeleted": "View deleted successfully",
"primaryColumnUpdated": "Onnistunut päivitys ensisijaiseksi sarakkeeksi",
"tableDataExported": "Kaikki taulukon tiedot on viety onnistuneesti",

620
packages/nc-gui/lang/fr.json

@ -1,5 +1,45 @@
{
"dashboards": {
"create_new_dashboard_project": "Create New Interface",
"connect_data_sources": "Connect data sources",
"alert": "Alert",
"alert-message": "No databases have been connected. Connect database bases to build interfaces. Skip this step and add databases from the base home page later.",
"select_database_projects_that_you_want_to_link_to_this_dashboard_projects": "Select Database Bases that you want to link to this Interface.",
"create_interface": "Create interface",
"project_name": "Base Name",
"connect": "Connect",
"buttonActionTypes": {
"open_external_url": "Open external link",
"delete_record": "Delete record",
"update_record": "Update record",
"open_layout": "Open layout"
},
"widgets": {
"static_text": "Text",
"chart": "Chart",
"table": "Table",
"image": "Image",
"map": "Map",
"button": "Button",
"number": "Number",
"bar_chart": "Bar Chart",
"line_chart": "Line Chart",
"area_chart": "Area Chart",
"pie_chart": "Pie Chart",
"donut_chart": "Donut Chart",
"scatter_plot": "Scatter Plot",
"bubble_chart": "Bubble Chart",
"radar_chart": "Radar Chart",
"polar_area_chart": "Polar Area Chart",
"radial_bar_chart": "Radial Bar Chart",
"heatmap_chart": "Heatmap Chart",
"treemap_chart": "Treemap Chart",
"box_plot_chart": "Box Plot Chart",
"candlestick_chart": "Candlestick Chart"
}
},
"general": {
"quit": "Quit",
"home": "Accueil",
"load": "Charger",
"open": "Ouvert",
@ -7,27 +47,67 @@
"yes": "Oui",
"no": "Non",
"ok": "D'accord",
"back": "Back",
"and": "Et",
"or": "Ou",
"add": "Ajouter",
"edit": "Éditer",
"link": "Link",
"links": "Links",
"remove": "Supprimer",
"import": "Import",
"logout": "Log Out",
"empty": "Empty",
"changeIcon": "Change Icon",
"save": "Sauvegarder",
"available": "Available",
"abort": "Abort",
"saving": "Saving",
"cancel": "Annuler",
"null": "Null",
"escape": "Escape",
"hex": "Hex",
"clear": "Clear",
"slack": "Slack",
"comment": "Comment",
"microsoftTeams": "Microsoft Teams",
"discord": "Discord",
"matterMost": "Mattermost",
"twilio": "Twilio",
"whatsappTwilio": "WhatsApp Twilio",
"quote": "Quote",
"submit": "Soumettre",
"create": "Créer",
"createEntity": "Create {entity}",
"creating": "Creating",
"creatingEntity": "Creating {entity}",
"details": "Details",
"skip": "Skip",
"code": "Code",
"duplicate": "Dupliquer",
"duplicating": "Duplicating",
"activate": "Activate",
"action": "Action",
"insert": "Insérer",
"delete": "Supprimer",
"deleteEntity": "Delete {entity}",
"bulkInsert": "Bulk Insert",
"bulkDelete": "Bulk Delete",
"bulkUpdate": "Bulk Update",
"deleting": "Deleting",
"update": "Mettre à jour",
"rename": "Renommer",
"reload": "Recharger",
"reset": "Réinitialiser",
"install": "Installer",
"show": "Montrer",
"access": "Access",
"visibility": "Visibility",
"hide": "Cacher",
"deprecated": "Deprecated",
"showAll": "Tout afficher",
"hideAll": "Tout cacher",
"notFound": "Not found",
"showMore": "Afficher davantage",
"showOptions": "Afficher les options",
"hideOptions": "Masquer les options",
@ -39,7 +119,7 @@
"signIn": "Connexion",
"signOut": "Se déconnecter",
"required": "Requise",
"enableScanner": "Enable Scanner for filling",
"enableScanner": "Permettre la saisie par scanner",
"preferred": "Préférée",
"mandatory": "Obligatoire",
"loading": "Chargement ...",
@ -47,6 +127,8 @@
"upload": "Téléverser",
"download": "Télécharger",
"default": "Défaut",
"base": "Source",
"datasource": "Data Source",
"more": "Plus",
"less": "Moins",
"event": "Événement",
@ -54,12 +136,14 @@
"after": "Après",
"before": "Avant",
"search": "Rechercher",
"searchIn": "Search In",
"notification": "Notification",
"reference": "Référence",
"function": "Fonction",
"confirm": "Confirmer",
"generate": "Générer",
"copy": "Copier",
"are": "are",
"misc": "Divers",
"lock": "Verrouiller",
"unlock": "Déverrouiller",
@ -76,9 +160,39 @@
"hideField": "Masquer le champ",
"sortAsc": "Trier par ordre croissant",
"sortDesc": "Trier par ordre décroissant",
"geoDataField": "GeoData Field"
"move": "Move",
"geoDataField": "Champ de données géographiques (GeoData)",
"type": "Type",
"name": "Name",
"changes": "Changes",
"new": "New",
"old": "Old",
"data": "Data",
"source": "Source",
"destination": "Destination",
"active": "Active",
"inactive": "Inactive",
"linked": "linked",
"finish": "Finish",
"min": "Min",
"max": "Max",
"avg": "Avg",
"sum": "Sum",
"count": "Count",
"countDistinct": "Count Distinct",
"sumDistinct": "Sum Distinct",
"avgDistinct": "Avg Distinct",
"join": "Join",
"options": "Options",
"primaryValue": "Primary Value",
"useSurveyMode": "Use Survey Mode",
"shift": "Shift",
"enter": "Enter",
"seconds": "Seconds"
},
"objects": {
"workspace": "Workspace",
"workspaces": "Workspaces",
"project": "Projet",
"projects": "Projets",
"table": "Tableau",
@ -95,6 +209,7 @@
"webhooks": "Webhooks",
"view": "Vue",
"views": "Vues",
"sidebar": "Sidebar",
"viewType": {
"grid": "Grille",
"gallery": "Galerie",
@ -107,16 +222,27 @@
"users": "Utilisateurs",
"role": "Rôle",
"roles": "Rôles",
"developer": "Developer",
"roleType": {
"owner": "Propriétaire",
"creator": "Créateur",
"editor": "Éditeur",
"commenter": "Commentateur",
"viewer": "Lecture seule",
"noaccess": "No Access",
"superAdmin": "Super Admin",
"orgLevelCreator": "Créateur au niveau de l'organisation",
"orgLevelViewer": "Visualiseur de niveau d'organisation"
},
"sqlVIew": "Vue SQL"
"sqlVIew": "Vue SQL",
"rowHeight": "Record Height",
"heightClass": {
"short": "Short",
"medium": "Medium",
"tall": "Tall",
"extra": "Extra"
},
"externalDb": "External Database"
},
"datatype": {
"ID": "Identifiant",
@ -171,17 +297,63 @@
"isNotNull": "est non null"
},
"title": {
"docs": "Docs",
"forum": "Forum",
"parameter": "Parameter",
"headers": "Headers",
"parameterName": "Parameter Name",
"currencyLocale": "Currency Locale",
"currencyCode": "Currency Code",
"searchMembers": "Search Members",
"noMembersFound": "No members found",
"dateJoined": "Date Joined",
"tokenName": "Token name",
"inDesktop": "in Desktop",
"rowData": "Record data",
"creator": "Creator",
"qrCode": "QR Code",
"termsOfService": "Terms of Service",
"updateSelectedRows": "Update Selected Records",
"noFiltersAdded": "No filters added",
"editCards": "Edit Cards",
"noFieldsFound": "No fields found",
"displayValue": "Display Value",
"expand": "Expand",
"hideAll": "Hide all",
"hideSystemFields": "Hide system fields",
"removeFile": "Remove File",
"hasMany": "Has Many",
"manyToMany": "Many to Many",
"virtualRelation": "Virtual Relation",
"linkMore": "Link More",
"linkMoreRecords": "Link more records",
"downloadFile": "Download File",
"renameTable": "Rename Table",
"renamingTable": "Renaming Table",
"renamingWs": "Renaming Workspace",
"renameWs": "Rename Workspace",
"deleteWs": "Delete Workspace",
"deletingWs": "Deleting Workspace",
"copyAuthToken": "Copy Auth Token",
"copiedAuthToken": "Copied Auth Token",
"copyInviteToken": "Copy Invite Token",
"showSidebar": "Show Sidebar",
"hideSidebar": "Hide Sidebar",
"creatingTable": "Creating Table",
"erdView": "Vue ERD",
"newBase": "New Data Source",
"newProj": "Nouveau projet",
"createBase": "Create Base",
"myProject": "Mes projets",
"formTitle": "Intitulé du formulaire",
"collabView": "Vue collaborative",
"lockedView": "Vue verrouillée",
"personalView": "Vue personnelle",
"collaborative": "Collaborative",
"locked": "Locked",
"personal": "Personal",
"appStore": "Magasin d'applications",
"teamAndAuth": "Équipe & Authentification",
"rolesUserMgmt": "Gestion des utilisateurs & rôles",
"userMgmt": "Gestion des utilisateurs",
"apiTokens": "API Tokens",
"apiTokenMgmt": "Gestion des jetons API",
"rolesMgmt": "Gestion des rôles",
"projMeta": "Métadonnées du projet",
@ -204,20 +376,129 @@
"generateToken": "Générer un jeton",
"APIsAndSupport": "API & Assistance",
"helpCenter": "Centre d'aide",
"noLabels": "No Labels",
"swaggerDocumentation": "Documentation de Swagger",
"quickImportFrom": "Importation rapide de",
"quickImport": "Importation rapide",
"quickImportAirtable": "Quick Import - Airtable",
"quickImportCSV": "Quick Import - CSV",
"quickImportExcel": "Quick Import - Excel",
"quickImportJSON": "Quick Import - JSON",
"jsonEditor": "JSON Editor",
"comingSoon": "Coming Soon",
"advancedSettings": "Paramètres avancés",
"codeSnippet": "Extrait de code",
"keyboardShortcut": "Raccourcis clavier",
"generateRandomName": "Générer un nom aléatoire",
"findRowByScanningCode": "Find row by scanning a QR or Barcode"
"findRowByScanningCode": "Find row by scanning a QR or Barcode",
"tokenManagement": "Token Management",
"addNewToken": "Add new token",
"accountSettings": "Account Settings",
"resetPasswordMenu": "Reset Password",
"tokens": "Tokens",
"userManagement": "User Management",
"accountManagement": "Account management",
"licence": "Licence",
"allowAllMimeTypes": "Allow All Mime Types",
"defaultView": "Default View",
"relations": "Relations",
"switchLanguage": "Switch Language",
"renameFile": "Rename File",
"links": {
"noAction": "No Action",
"cascade": "Cascade",
"restrict": "Restrict",
"setNull": "Set NULL",
"setDefault": "Set Default"
}
},
"labels": {
"heading1": "Heading 1",
"heading2": "Heading 2",
"heading3": "Heading 3",
"bold": "Bold",
"italic": "Italic",
"underline": "Underline",
"strike": "Strike",
"taskList": "Task List",
"bulletList": "Bullet List",
"numberedList": "Numbered List",
"downloadData": "Download Data",
"blockQuote": "Block Quote",
"noToken": "No Token",
"tokenLimit": "Only one token per user is allowed",
"duplicateAttachment": "File with name {filename} already attached",
"viewIdColon": "VIEW ID: {viewId}",
"toAddress": "To Address",
"subject": "Subject",
"body": "Body",
"commaSeparatedMobileNumber": "Comma separated Mobile #",
"headerName": "Header Name",
"icon": "Icon",
"max": "Max",
"enableRichText": "Enable Rich Text",
"idColon": "Id:",
"copiedRecordURL": "Copied Record URL",
"copyRecordURL": "Copy Record URL",
"duplicateRecord": "Duplicate record",
"binaryEncodingFormat": "Binary encoding format",
"syntax": "Syntax",
"examples": "Examples",
"durationInfo": "A duration of time in minutes or seconds (e.g. 1:23).",
"addHeader": "Add Header",
"enterDefaultUrlOptional": "Enter default URL (Optional)",
"negative": "Negative",
"discard": "Discard",
"default": "Default",
"defaultNumberPercent": "Default Number (%)",
"durationFormat": "Duration Format",
"dateFormat": "Date Format",
"timeFormat": "Time Format",
"singularLabel": "Singular Label",
"pluralLabel": "Plural Label",
"optional": "(Optional)",
"clickToMake": "Click to make",
"visibleForRole": "visible for role:",
"inUI": "in UI Dashboard",
"projectSettings": "Base Settings",
"clickToHide": "Click to hide",
"clickToDownload": "Click to download",
"forRole": "for role",
"clickToCopyViewID": "Click to copy View ID",
"viewMode": "View Mode",
"searchUsers": "Search Users",
"superAdmin": "Super Admin",
"allTables": "All Tables",
"members": "Members",
"dataSources": "Data Sources",
"connectDataSource": "Connect a Data Source",
"searchProjects": "Search Bases",
"createdBy": "Créé par",
"viewingAttachmentsOf": "Viewing Attachments of",
"readOnly": "Readonly",
"dropHere": "Drop here",
"createdOn": "Created On",
"notifyVia": "Notifier via",
"projName": "Nom du projet",
"profile": "Profile",
"accountDetails": "Account Details",
"controlAppearance": "Control your Appearance.",
"accountEmailID": "Account Email ID",
"backToWorkspace": "Back to Workspace",
"untitledToken": "Untitled token",
"tableName": "Nom du tableau",
"dashboardName": "Dashboard name",
"createView": "Create a View",
"creatingView": "Creating View",
"duplicateView": "Duplicate View",
"duplicateGridView": "Duplicate Grid View",
"createGridView": "Create Grid View",
"duplicateGalleryView": "Duplicate Gallery View",
"createGalleryView": "Create Gallery View",
"duplicateFormView": "Duplicate Form View",
"createFormView": "Create Form View",
"duplicateKanbanView": "Duplicate Kanban View",
"createKanbanView": "Create Kanban View",
"viewName": "Vue",
"viewLink": "Lien de vue",
"columnName": "Nom de la colonne",
@ -238,7 +519,7 @@
"action": "Action",
"actions": "Actions",
"operation": "Opération",
"operationSub": "Sub Operation",
"operationSub": "Sous-opération",
"operationType": "Type d'opération",
"operationSubType": "Sous-type d'opération",
"description": "Description",
@ -247,6 +528,14 @@
"where": "Où",
"cache": "Cache",
"chat": "Discussion",
"showOrHide": "Show or Hide",
"airtable": "Airtable",
"csv": "CSV",
"csvFile": "CSV File",
"json": "JSON",
"jsonFile": "JSON File",
"excel": "Excel",
"microsoftExcel": "Microsoft Excel",
"email": "Courriel",
"storage": "Stockage",
"uiAcl": "IU ACL",
@ -255,14 +544,15 @@
"created": "Créé",
"sqlOutput": "Sortie SQL",
"addOption": "Ajouter une option",
"interfaceColor": "Interface Color",
"qrCodeValueColumn": "Colonne avec une valeur code QR",
"barcodeValueColumn": "Colonne avec une valeur code-barres",
"barcodeFormat": "Format du code-barres",
"qrCodeValueTooLong": "Trop de caractères pour un code QR",
"barcodeValueTooLong": "Trop de caractères pour un code-barres",
"currentLocation": "Emplacement actuel",
"lng": "Lng",
"lat": "Lat",
"lng": "Long.",
"lat": "Lat.",
"aggregateFunction": "Fonction agrégée",
"dbCreateIfNotExists": "Base de données : la créer si elle n'existe pas",
"clientKey": "Clé client",
@ -282,13 +572,17 @@
"joinDiscord": "Rejoindre le serveur Discord",
"joinCommunity": "Rejoindre la communauté NocoDB",
"joinReddit": "Rejoindre /r/NocoDB",
"followNocodb": "Suivre NocoDB"
"followNocodb": "Suivre NocoDB",
"communityTranslated": "(Community Translated)"
},
"twitter": "Twitter",
"docReference": "Référence de document",
"selectUserRole": "Sélectionner le rôle d'utilisateur",
"childTable": "Table enfant",
"childColumn": "Colonne enfant",
"childField": "Child field",
"linkToAnotherRecord": "Lien vers un autre enregistrement",
"links": "Links",
"onUpdate": "Mise à jour en cours",
"onDelete": "Suppression en cours",
"account": "Compte",
@ -298,16 +592,21 @@
"customTheme": "Thème personnalisé",
"requestDataSource": "Demandez une source de données dont vous avez besoin ?",
"apiKey": "Clé d'API",
"sharedBase": "Base partagée",
"personalAccessToken": "Personal Access Token",
"sharedBaseUrl": "Shared Base URL",
"importData": "Importer des données",
"importSecondaryViews": "Importer des vues secondaires",
"importRollupColumns": "Importer des colonnes de rollup",
"importLookupColumns": "Importer des colonnes de recherche",
"importAttachmentColumns": "Importer des colonnes de pièces jointes",
"importFormulaColumns": "Importer des colonnes de formule",
"importUsers": "Import Users (by email)",
"noData": "Aucune donnée",
"goToDashboard": "Accéder au tableau de bord",
"importing": "Importation de",
"formatJson": "Format JSON",
"autoSelectFieldTypes": "Auto-Select Field Types",
"firstRowAsHeaders": "Use First Record as Headers",
"flattenNested": "Aplatir imbriqué",
"downloadAllowed": "Téléchargement autorisé",
"weAreHiring": "Nous recrutons !",
@ -325,9 +624,61 @@
"welcomeToNc": "Bienvenue sur NocoDB !",
"inviteOnlySignup": "Autoriser l'inscription en utilisant uniquement l'url d'invitation",
"nextRow": "Rang suivant",
"prevRow": "Rang précédent"
"prevRow": "Rang précédent",
"addRowGrid": "Manually add data in grid view",
"addRowForm": "Enter record data through a form",
"noAccess": "No access",
"restApis": "Rest APIs",
"apis": "APIs",
"includeData": "Include Data",
"includeView": "Include View",
"includeWebhook": "Include Webhook",
"zoomInToViewColumns": "Zoom in to view columns",
"embedInSite": "Embed this view in your site",
"titleRequired": "title is required.",
"sourceNameRequired": "Source name is required",
"changeWsName": "Change Workspace Name",
"pressEnter": "Press Enter",
"newFormLoaded": "New form will be loaded after"
},
"activity": {
"openInANewTab": "Open in a new tab",
"copyIFrameCode": "Copy IFrame code",
"onCondition": "On Condition",
"bulkDownload": "Bulk Download",
"attachFile": "Attach File",
"viewAttachment": "View Attachments",
"attachmentDrop": "Click or drop a file into cell",
"addFiles": "Add File(s)",
"hideInUI": "Hide in UI",
"addBase": "Add Base",
"addParameter": "Add Parameter",
"submitAnotherForm": "Submit Another Form",
"dragAndDropFieldsHereToAdd": "Drag and drop fields here to add",
"editSource": "Edit Data Source",
"enterText": "Enter text",
"okEditBase": "Ok & Edit Base",
"showInUI": "Show in UI",
"outOfSync": "Out of sync",
"newSource": "New Data Source",
"newWebhook": "New Webhook",
"enablePublicAccess": "Enable Public Access",
"doYouWantToSaveTheChanges": "Do you want to save the changes ?",
"editingAccess": "Editing access",
"enabledPublicViewing": "Enable public viewing",
"restrictAccessWithPassword": "Restrict access with password",
"manageProjectAccess": "Manage Base Access",
"allowDownload": "Allow Download",
"surveyMode": "Survey Mode",
"rtlOrientation": "RTL Orientation",
"useTheme": "Use Theme",
"copyLink": "Copy Link",
"copiedLink": "Link Copied",
"copyInviteLink": "Copy invite link",
"copiedInviteLink": "Copied invite link",
"copyUrl": "Copier le lien",
"moreColors": "More Colors",
"moveProject": "Move Base",
"createProject": "Créer un projet",
"importProject": "Importer un projet",
"searchProject": "Rechercher un projet",
@ -338,6 +689,7 @@
"deleteProject": "Supprimer le projet",
"refreshProject": "Actualiser les projets",
"saveProject": "Enregistrer le projet",
"saveAndQuit": "Save & Quit",
"deleteKanbanStack": "Supprimer la pile ?",
"createProjectExtended": {
"extDB": "Créer en se connectant<br>à une base de données externe",
@ -353,6 +705,7 @@
"translate": "Aider à la traduction",
"account": {
"authToken": "Copier le jeton d'authentification",
"authTokenCopied": "Copied Auth Token",
"swagger": "Swagger : API REST",
"projInfo": "Copier les informations du projet",
"themes": "Thèmes"
@ -362,7 +715,10 @@
"filter": "Filtre",
"addFilter": "Ajouter un filtre",
"share": "Partager",
"groupBy": "Group By",
"addSubGroup": "Add subgroup",
"shareBase": {
"label": "Share base",
"disable": "Désactiver la base partagée",
"enable": "N'importe qui disposant du lien",
"link": "Partager le lien de la base"
@ -372,6 +728,8 @@
"inviteTeam": "Inviter une équipe",
"inviteUser": "Inviter un utilisateur",
"inviteToken": "Inviter via un jeton",
"linkedRecords": "Linked Records",
"addNewLink": "Add New Link",
"newUser": "Nouvel utilisateur",
"editUser": "Modifier l'utilisateur",
"deleteUser": "Supprimer l'utilisateur du projet",
@ -386,8 +744,11 @@
"previousRecord": "Ligne précédente",
"copyApiURL": "Copier l'URL de l'API",
"createTable": "Créer une nouvelle table",
"createDashboard": "Create Dashboard",
"createWorkspace": "Create Workspace",
"refreshTable": "Actualiser le tableau",
"renameTable": "Renommer la table",
"renameLayout": "Layout Rename",
"deleteTable": "Supprimer la table",
"addField": "Ajouter un nouveau champ à ce tableau",
"setDisplay": "Définir comme valeur d'affichage",
@ -398,6 +759,9 @@
"insertRow": "Insérer une nouvelle ligne",
"duplicateRow": "Dupliquer la ligne",
"deleteRow": "Supprimer la ligne",
"deleteRows": "Delete records",
"predictColumns": "Predict Fields",
"predictFormulas": "Predict Formulas",
"deleteSelectedRow": "Supprimer les lignes sélectionnées",
"importExcel": "Importer depuis Excel",
"importCSV": "Importer un fichier CSV",
@ -413,11 +777,12 @@
"createView": "Créer une vue",
"shareView": "Partager la vue",
"findRowByCodeScan": "Find row by scan",
"fillByCodeScan": "Fill by scan",
"fillByCodeScan": "Remplir avec un scanner",
"listSharedView": "Liste de vues partagées",
"ListView": "Liste des vues",
"copyView": "Copier la vue",
"renameView": "Renommer la vue",
"uploadData": "Upload Data",
"deleteView": "Supprimer la vue",
"createGrid": "Créer une vue grille",
"createGallery": "Créer une vue galerie",
@ -425,14 +790,13 @@
"createKanban": "Créer une vue kanban",
"createForm": "Créer une vue formulaire",
"showSystemFields": "Afficher les champs système",
"copyUrl": "Copier le lien",
"openTab": "Ouvrir nouvel onglet",
"iFrame": "Copier le code HTML intégré",
"addWebhook": "Ajout un webhook",
"enableWebhook": "Enable Webhook",
"testWebhook": "Test Webhook",
"copyWebhook": "Copy Webhook",
"deleteWebhook": "Delete Webhook",
"enableWebhook": "Activer le Webhook",
"testWebhook": "Tester le Webhook",
"copyWebhook": "Copier le Webhook",
"deleteWebhook": "Supprimer le Webhook",
"newToken": "Ajout un nouveau jeton",
"exportZip": "Exporter un zip",
"importZip": "Importer un zip",
@ -451,10 +815,24 @@
"addFilterGroup": "Ajouter un groupe de filtres",
"linkRecord": "Fiche de liaison",
"addNewRecord": "Ajouter un nouvel enregistrement",
"newRecord": "New record",
"tableNameCreateNewRecord": "{tableName}: Create new record",
"gotSavedLinkedSuccessfully": "{tableName} '{recordTitle}' got saved & linked successfully",
"recordCreatedLinked": "Record Created & Linked",
"useConnectionUrl": "Utiliser l'URL de connexion",
"toggleCommentsDraw": "Afficher ou masquer le panneau des commentaires",
"expandRecord": "Développer le dossier",
"deleteRecord": "Supprimer l'enregistrement",
"fullWidth": "Full width",
"exitFullWidth": "Exit full width",
"markAllAsRead": "Mark all as read",
"column": {
"delete": "Delete Field",
"addNumber": "Add Number Field",
"addSingleLineText": "Add SingleLineText Field",
"addLongText": "Add LongText Field",
"addOther": "Add Other Field"
},
"erd": {
"showColumns": "Afficher les colonnes",
"showPkAndFk": "Afficher les clés primaires et étrangères",
@ -470,14 +848,16 @@
"addOrEditStack": "Ajouter / Modifier une pile"
},
"map": {
"mappedBy": "Mapped By",
"chooseMappingField": "Choose a Mapping Field",
"mappedBy": "Position basée sur",
"chooseMappingField": "Choisissez un champ de coordonnées géographiques",
"openInGoogleMaps": "Google Maps",
"openInOpenStreetMap": "OSM"
},
"toggleMobileMode": "Toggle Mobile Mode"
"toggleMobileMode": "(Dés-)activer le mode Mobile",
"startCommenting": "Start commenting!"
},
"tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment",
"saveChanges": "Sauvegarder les modifications",
"xcDB": "Créer un nouveau projet",
"extDB": "Base de données supportées MySQL, PostgreSQL, SQL Server & SQLite",
@ -488,6 +868,7 @@
"light": "Jour (^⇧B)"
},
"addTable": "Ajouter un nouveau tableau",
"addDashboard": "Add new Dashboard",
"inviteMore": "Inviter plus d'utilisateurs",
"toggleNavDraw": "Afficher ou masquer le panneau de navigation",
"reloadApiToken": "Recharger les jetons API",
@ -506,7 +887,19 @@
"clientCA": "Selectionner un fichier d'authentification"
},
"placeholder": {
"selectSlackChannels": "Select Slack channels",
"selectTeamsChannels": "Select Microsoft Teams channels",
"selectDiscordChannels": "Select Discord channels",
"selectMattermostChannels": "Select Mattermost channels",
"webhookTitle": "Webhook Title",
"barcodeColumn": "Select a field for the Barcode value",
"notFoundContent": "No valid field Type can be found.",
"selectBarcodeFormat": "Select a Barcode format",
"projName": "Saisir le nom du projet",
"selectGroupField": "Select a Grouping Field",
"selectGroupFieldNotFound": "No Single Select Field can be found. Please create one first.",
"selectGeoField": "Select a GeoData Field",
"selectGeoFieldNotFound": "No GeoData Field can be found. Please create one first.",
"password": {
"enter": "Saisir le mot de passe",
"current": "Mot de passe actuel",
@ -514,6 +907,8 @@
"save": "Enregistrer le mot de passe",
"confirm": "Confirmer le nouveau mot de passe"
},
"selectAColumnForTheQRCodeValue": "Select a field for the QR code value",
"allowNegativeNumbers": "Allow negative numbers",
"searchProjectTree": "Chercher un tableau",
"searchFields": "Champ de recherche",
"searchColumn": "Recherche {recherche} colonne",
@ -523,34 +918,152 @@
"defaultValue": "Valeur par défaut",
"filterByEmail": "Rechercher un courriel",
"filterQuery": "Rechercher",
"selectField": "Sélectionner un champ"
"selectField": "Sélectionner un champ",
"precision": "Precision",
"decimal1": "1.0",
"decimal2": "1.00",
"decimal3": "1.000",
"decimal4": "1.0000",
"decimal5": "1.00000",
"decimal6": "1.000000",
"decimal7": "1.0000000",
"decimal8": "1.00000000",
"value": "Value",
"key": "Key"
},
"msg": {
"clickToCopyFieldId": "Click to copy Field Id",
"enterPassword": "Enter password",
"bySigningUp": "By signing up, you agree to the",
"subscribeToOurWeeklyNewsletter": "Subscribe to our weekly newsletter",
"verifyingPassword": "Verifying Password",
"thisSharedViewIsProtected": "This shared view is protected",
"successfullySubmittedFormData": "Successfully submitted form data",
"formViewNotSupportedOnMobile": "Form view is not supported on mobile",
"newFormWillBeLoaded": "New form will be loaded after {seconds} seconds",
"optimizedQueryDisabled": "Optimized query is disabled",
"optimizedQueryEnabled": "Optimized query is enabled",
"lookupNonBtWarning": "Lookup field is not supported for non-Belongs to relation",
"invalidTime": "Invalid Time",
"linkColumnClearNotSupportedYet": "You don't have any supported links for Lookup",
"recordCouldNotBeFound": "Record could not be found",
"invalidPhoneNumber": "Invalid phone number",
"pageSizeChanged": "Page size changed",
"errorLoadingData": "Error loading data",
"webhookBodyMsg1": "Use context variable",
"webhookBodyMsg2": "body",
"webhookBodyMsg3": "to refer the record under consideration",
"formula": {
"hintStart": "Hint: Use {placeholder1} to reference fields, e.g: {placeholder2}. For more, please check out",
"hintEnd": "Formulas.",
"noSuggestedFormulaFound": "No suggested formula found",
"numericTypeIsExpected": "Numeric type is expected",
"stringTypeIsExpected": "String type is expected",
"operationNotAvailable": "{operation} operation not available",
"cantSaveFieldFormulaInvalid": "Can’t save field because formula is invalid",
"notSupportedToReferenceColumn": "Not supported to reference field {columnName}",
"typeIsExpectedButFound": "Type {type} is expected but found Type {found}",
"requiredArgumentsFormula": "{calleeName} requires {requiredArguments} arguments",
"minRequiredArgumentsFormula": "{calleeName} required minimum {minRequiredArguments} arguments",
"maxRequiredArgumentsFormula": "{calleeName} required maximum {maxRequiredArguments} arguments",
"functionNotAvailable": "{function} function is not available",
"firstParamWeekDayHaveDate": "The first parameter of WEEKDAY() should have date value",
"secondParamWeekDayHaveDate": "The second parameter of WEEKDAY() should have the value either \"sunday\", \"monday\", \"tuesday\", \"wednesday\", \"thursday\", \"friday\" or \"saturday\"",
"firstParamDateAddHaveDate": "The first parameter of DATEADD() should have date value",
"secondParamDateAddHaveNumber": "The second parameter of DATEADD() should have numeric value",
"thirdParamDateAddHaveDate": "The third parameter of DATEADD() should have the value either \"day\", \"week\", \"month\" or \"year\"",
"firstParamDateDiffHaveDate": "The first parameter of DATEDIFF() should have date value",
"secondParamDateDiffHaveDate": "The second parameter of DATEDIFF() should have date value",
"thirdParamDateDiffHaveDate": "The third parameter of DATETIME_DIFF() should have value either \"milliseconds\", \"ms\", \"seconds\", \"s\", \"minutes\", \"m\", \"hours\", \"h\", \"days\", \"d\", \"weeks\", \"w\", \"months\", \"M\", \"quarters\", \"Q\", \"years\", or \"y\"",
"columnNotAvailable": "Field {columnName} is not available",
"cantSaveCircularReference": "Can’t save field because it causes a circular reference",
"columnWithTypeFoundButExpected": "Field {columnName} with {columnType} type is found but {expectedType} type is expected",
"columnNotMatchedWithType": "{columnName} is not matched with {columnType}"
},
"selectOption": {
"cantBeNull": "Select options can't be null",
"multiSelectCantHaveCommas": "MultiSelect fields can't have commas(',')",
"cantHaveDuplicates": "Select options can't have duplicates",
"createNewOptionNamed": "Create new option named"
},
"plsEnterANumber": "Please enter a number",
"plsInputEmail": "Please input email",
"invalidDate": "Invalid date",
"invalidLocale": "Invalid locale",
"invalidCurrencyCode": "Invalid Currency Code",
"postgresHasItsOwnCurrencySettings": "PostgreSQL 'money' type has own currency settings",
"validColumnsForBarCode": "The valid Field Types for a Barcode Field are: Number, Single Line Text, Long Text, Phone Number, URL, Email, Decimal. Please create one first.",
"hm": {
"title": "Has Many Relation",
"tooltip_desc": "A single record from table ",
"tooltip_desc2": " can be linked with multiple records from table "
},
"mm": {
"title": "Many to Many Relation",
"tooltip_desc": "Multiple records from table ",
"tooltip_desc2": " can be linked with multiple records from table "
},
"bt": {
"title": "Belongs to Relation",
"tooltip_desc": "A single record from table ",
"tooltip_desc2": " can be linked with a record from table "
},
"oo": {
"title": "One to One Relation",
"tooltip_desc": "A single record from table ",
"tooltip_desc2": " can be linked with a single record from table "
},
"noRecordsAreLinkedFromTable": "No records are linked from table",
"noRecordsLinked": "No records linked",
"recordsLinked": "records linked",
"acceptOnlyValid": "Accepts only",
"apiTokenCreate": "Create personal API tokens to use in automation or external apps.",
"selectFieldToSort": "Select Field to Sort",
"thereAreNoRecordsInTable": "There are no records in table",
"createWebhookMsg1": "Get started with web-hooks!",
"createWebhookMsg2": "Create web-hooks to power you automations,",
"createWebhookMsg3": "Get notified as soon as there are changes in your data",
"areYouSureUWantTo": "Are you sure you want to delete the following",
"areYouSureUWantToDeleteLabel": "Are you sure you want to {deleteLabel} the following",
"idColumnRequired": "ID field is required, you can rename this later if required.",
"length59Required": "The length exceeds the max 59 characters",
"noNewNotifications": "You have no new notifications",
"noRecordFound": "Record not found",
"rowDeleted": "Record deleted",
"saveChanges": "Do you want to save the changes?",
"tooLargeFieldEntity": "The field is too large to be converted to {entity}",
"roleRequired": "Role required",
"warning": {
"dbValid": "Please make sure database you are trying to connect is valid! This operation can cause schema loss!!",
"barcode": {
"renderError": "Erreur de code-barres - veuillez vérifier la compatibiltié entre la donnée d'entrée et le type de code-barres"
},
"nonEditableFields": {
"computedFieldUnableToClear": "Avertissement : Champ calculé - impossible d'effacer le texte",
"qrFieldsCannotBeDirectlyChanged": "Attention : les champs QR code ne peuvent pas être modifiés directement."
}
"qrFieldsCannotBeDirectlyChanged": "Attention : les champs QR code ne peuvent pas être modifiés directement.",
"barcodeFieldsCannotBeDirectlyChanged": "Warning: Barcode fields cannot be directly changed."
},
"duplicateProject": "Are you sure you want to duplicate the base?",
"duplicateTable": "Are you sure you want to duplicate the table?"
},
"info": {
"disabledAsViewLocked": "Disabled as View is locked",
"basesMigrated": "Bases are migrated. Please try again.",
"pasteNotSupported": "L'opération de collage n'est pas prise en charge sur la cellule active",
"roles": {
"orgCreator": "Le créateur peut créer de nouveaux projets et accéder à tout projet invité.",
"orgViewer": "Le visualisateur n'est pas autorisé à créer de nouveaux projets mais il peut accéder à tout projet invité."
},
"codeScanner": {
"loadingScanner": "Loading the scanner...",
"loadingScanner": "Chargement du scanner...",
"selectColumn": "Select a column (QR code or Barcode) that you want to use for finding a row by scanning.",
"moreThanOneRowFoundForCode": "More than one row found for this code. Currently only unique codes are supported.",
"noRowFoundForCode": "No row found for this code for the selected column"
},
"map": {
"overLimit": "Vous avez dépassé la limite.",
"closeLimit": "You're getting close to the limit.",
"limitNumber": "The limit of markers shown in a Map View is 1000 records."
"closeLimit": "Vous vous approchez de la limite.",
"limitNumber": "Une carte ne peut pas afficher plus de 1000 points."
},
"footerInfo": "Lignes par page",
"upload": "Sélectionner un fichier à téléverser",
@ -637,9 +1150,12 @@
"map": "Ajouter la vue Carte",
"calendar": "Ajouter une vue Calendrier"
},
"tablesMetadataInSync": "Les métadonnées de tables sont en synchronisation",
"tablesMetadataInSync": "Les métadonnées des tables sont synchronisées",
"addMultipleUsers": "Vous pouvez ajouter plusieurs courriels séparés par des virgules (,)",
"enterTableName": "Entrez le nom du tableau",
"enterLayoutName": "Enter Layout name",
"enterDashboardName": "Enter Dashboard name",
"defaultColumns": "Default fields",
"addDefaultColumns": "Ajouter des colonnes par défaut",
"tableNameInDb": "Nom de la table tel qu'enregistré dans la base de données",
"airtable": {
@ -662,30 +1178,54 @@
"valueAlreadyInList": "Cette valeur figure déjà dans la liste",
"noColumnsToUpdate": "Aucune colonne à mettre à jour",
"tableDeleted": "Tableau supprimé avec succès",
"layoutDeleted": "Deleted layout successfully",
"generatePublicShareableReadonlyBase": "Génère une base publique partagée en lecture seule",
"deleteViewConfirmation": "Êtes-vous sûr de vouloir effacer cette vue ?",
"deleteLayoutConfirmation": "Are you sure you want to delete this Layout?",
"deleteTableConfirmation": "Voulez-vous supprimer ce tableau",
"showM2mTables": "Afficher les tables plusieurs à plusieurs",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"showM2mTablesDesc": "La relation de plusieurs à plusieurs est prise en charge par une table de jonction, qui est cachée par défaut. Activez cette option pour afficher les tables de jonction.",
"showNullInCells": "Afficher NULL dans les cellules",
"showNullInCellsDesc": "Affichez le texte 'NULL' dans les cellules contenant une valeur NULL. Cela permet de les différencier des cellules contenant une chaîne de caractères VIDE.",
"showNullAndEmptyInFilter": "Afficher NULL et EMPTY (vide) dans le filtre",
"showNullAndEmptyInFilterDesc": "Activez les filtres \"supplémentaires\" pour distinguer les cellules contenant des chaînes NULL et vides. Par défaut, \"blanc\" traite les chaînes NULL et vides de la même manière.",
"deleteKanbanStackConfirmation": "La suppression de cette pile entraînera également la suppression de l'option de sélection `{stackToBeDeleted}` de la pile `{groupingField}`. Les enregistrements seront déplacés vers la pile non catégorisée.",
"computedFieldEditWarning": "Champ calculé : le contenu est en lecture seule. Utilisez le menu d'édition des colonnes pour reconfigurer",
"computedFieldDeleteWarning": "Champ calculé : le contenu est en lecture seule. Impossible d'effacer le contenu.",
"noMoreRecords": "Plus d'enregistrements"
"noMoreRecords": "Plus d'enregistrements",
"tokenNameNotEmpty": "Token name should not be empty",
"tokenNameMaxLength": "Token name should not be more than 255 characters",
"dbNameRequired": "Database name is required",
"wsNameRequired": "Workspace name required",
"wsNameMinLength": "Workspace name must be at least 3 characters long",
"wsNameMaxLength": "Workspace name must be at most 50 characters long",
"wsDeleteDlg": "Delete this workspace and all it’s contents.",
"userConfirmation": "I understand that this action is irreversible",
"pageNotFound": "Page Not Found",
"makeLineBreak": "to make a line break",
"goToPrevious": "Go to previous",
"goToNext": "Go to next",
"thankYou": "Thank you!",
"submittedFormData": "You have successfully submitted the form data."
},
"error": {
"nameRequired": "Name Required",
"nameMinLength": "Name must be at least 2 characters long",
"nameMaxLength": "Name must be at most 60 characters long",
"viewNameRequired": "View name is required",
"nameMaxLength256": "Name must be at most 256 characters long",
"viewNameUnique": "View name should be unique",
"searchProject": "Votre recherche pour {search} n'a renvoyé aucun résultat",
"invalidChar": "Caractère invalide dans le chemin du dossier.",
"invalidDbCredentials": "Identifiants de base de données invalides.",
"unableToConnectToDb": "Connexion impossible à la base de données, merci de vérifier que la base de données est démarrée et accessible.",
"invalidYear": "Invalid year",
"userDoesntHaveSufficientPermission": "L’utilisateur n’existe pas ou n’a pas les permissions suffisantes pour créer le schéma.",
"dbConnectionStatus": "Paramètres de base de données non valides",
"dbConnectionFailed": "Echec de connexion :",
"nullFilterExists": "Null filter exists. Please remove them",
"signUpRules": {
"emailReqd": "Adresse mail requise",
"emailRequired": "Email is required",
"emailInvalid": "L'adresse électronique doit être valide",
"passwdRequired": "Mot de passe requis",
"passwdLength": "Votre mot de passe doit contenir au moins 8 caractères",
@ -695,7 +1235,9 @@
"atLeastOneUppercase": "Une lettre majuscule",
"atLeastOneNumber": "Un chiffre",
"atLeastOneSpecialChar": "Un caractère spécial",
"allowedSpecialCharList": "Liste des caractères spéciaux autorisés"
"allowedSpecialCharList": "Liste des caractères spéciaux autorisés",
"invalidEmails": "Invalid emails",
"invalidEmail": "Invalid Email"
},
"invalidURL": "URL invalide",
"invalidEmail": "Email invalide",
@ -726,6 +1268,8 @@
"nameShouldStartWithAnAlphabetOr_": "Le nom doit commencer par une lettre de l'alphabet ou _",
"followingCharactersAreNotAllowed": "Les caractères suivants ne sont pas autorisés",
"columnNameRequired": "Nom de la colonne requis",
"duplicateColumnName": "Duplicate field name",
"uiDataTypeRequired": "UI data type is required",
"columnNameExceedsCharacters": "The length of column name exceeds the max {value} characters",
"projectNameExceeds50Characters": "Le nom du projet dépasse les 50 caractères",
"projectNameCannotStartWithSpace": "Le nom du projet ne peut pas commencer par un espace",
@ -758,6 +1302,7 @@
"futureRelease": "Bientôt disponible !"
},
"success": {
"licenseKeyUpdated": "License Key Updated",
"columnDuplicated": "Colonne dupliquée avec succès",
"rowDuplicatedWithoutSavedYet": "Row duplicated (not saved)",
"updatedUIACL": "Mise à jour réussie de l'ACL de l'interface utilisateur pour les tables",
@ -765,6 +1310,7 @@
"pluginSettingsSaved": "Les paramètres du plugin ont été enregistrés avec succès",
"pluginTested": "Testé avec succès les paramètres du plugin",
"tableRenamed": "Tableau renommé avec succès",
"layoutRenamed": "Layout renamed successfully",
"viewDeleted": "Vue effacée avec succès",
"primaryColumnUpdated": "Mis à jour avec succès comme colonne primaire",
"tableDataExported": "Toutes les données du tableau ont été exportées avec succès",

698
packages/nc-gui/lang/he.json

File diff suppressed because it is too large Load Diff

582
packages/nc-gui/lang/hi.json

@ -1,5 +1,45 @@
{
"dashboards": {
"create_new_dashboard_project": "Create New Interface",
"connect_data_sources": "Connect data sources",
"alert": "Alert",
"alert-message": "No databases have been connected. Connect database bases to build interfaces. Skip this step and add databases from the base home page later.",
"select_database_projects_that_you_want_to_link_to_this_dashboard_projects": "Select Database Bases that you want to link to this Interface.",
"create_interface": "Create interface",
"project_name": "Base Name",
"connect": "Connect",
"buttonActionTypes": {
"open_external_url": "Open external link",
"delete_record": "Delete record",
"update_record": "Update record",
"open_layout": "Open layout"
},
"widgets": {
"static_text": "Text",
"chart": "Chart",
"table": "Table",
"image": "Image",
"map": "Map",
"button": "Button",
"number": "Number",
"bar_chart": "Bar Chart",
"line_chart": "Line Chart",
"area_chart": "Area Chart",
"pie_chart": "Pie Chart",
"donut_chart": "Donut Chart",
"scatter_plot": "Scatter Plot",
"bubble_chart": "Bubble Chart",
"radar_chart": "Radar Chart",
"polar_area_chart": "Polar Area Chart",
"radial_bar_chart": "Radial Bar Chart",
"heatmap_chart": "Heatmap Chart",
"treemap_chart": "Treemap Chart",
"box_plot_chart": "Box Plot Chart",
"candlestick_chart": "Candlestick Chart"
}
},
"general": {
"quit": "Quit",
"home": "घर",
"load": "भर",
"open": "खआ",
@ -7,27 +47,67 @@
"yes": "ह",
"no": "नह",
"ok": "ठक ह",
"back": "Back",
"and": "और",
"or": "य",
"add": "ज",
"edit": "सदन करन",
"link": "Link",
"links": "Links",
"remove": "हट",
"import": "Import",
"logout": "Log Out",
"empty": "Empty",
"changeIcon": "Change Icon",
"save": "बच",
"available": "Available",
"abort": "Abort",
"saving": "Saving",
"cancel": "रदद करन",
"null": "Null",
"escape": "Escape",
"hex": "Hex",
"clear": "Clear",
"slack": "Slack",
"comment": "Comment",
"microsoftTeams": "Microsoft Teams",
"discord": "Discord",
"matterMost": "Mattermost",
"twilio": "Twilio",
"whatsappTwilio": "WhatsApp Twilio",
"quote": "Quote",
"submit": "परसत करन",
"create": "सजन करन",
"createEntity": "Create {entity}",
"creating": "Creating",
"creatingEntity": "Creating {entity}",
"details": "Details",
"skip": "Skip",
"code": "Code",
"duplicate": "Duplicate",
"insert": "Insert",
"duplicating": "Duplicating",
"activate": "Activate",
"action": "Action",
"insert": "शिल कर",
"delete": "मि",
"deleteEntity": "Delete {entity}",
"bulkInsert": "Bulk Insert",
"bulkDelete": "Bulk Delete",
"bulkUpdate": "Bulk Update",
"deleting": "Deleting",
"update": "अदयतन",
"rename": "नम बदल",
"reload": "पड कर",
"reset": "रट",
"install": "सित करन",
"show": "परदरशन",
"access": "Access",
"visibility": "Visibility",
"hide": "छि",
"deprecated": "Deprecated",
"showAll": "सब दि",
"hideAll": "सभि",
"notFound": "Not found",
"showMore": "और दिओ",
"showOptions": "विकलप दि",
"hideOptions": "विकलप छि",
@ -47,6 +127,8 @@
"upload": "डलन",
"download": "निलन",
"default": "Default",
"base": "Source",
"datasource": "Data Source",
"more": "ज",
"less": "कम",
"event": "घटन",
@ -54,12 +136,14 @@
"after": "बद म",
"before": "पहल",
"search": "ख",
"searchIn": "Search In",
"notification": "सित कर",
"reference": "सदरभ",
"function": "समह",
"confirm": "Confirm",
"generate": "Generate",
"copy": "Copy",
"are": "are",
"misc": "Miscellaneous",
"lock": "Lock",
"unlock": "Unlock",
@ -76,9 +160,39 @@
"hideField": "Hide Field",
"sortAsc": "Sort Ascending",
"sortDesc": "Sort Descending",
"geoDataField": "GeoData Field"
"move": "Move",
"geoDataField": "GeoData Field",
"type": "Type",
"name": "Name",
"changes": "Changes",
"new": "New",
"old": "Old",
"data": "Data",
"source": "Source",
"destination": "Destination",
"active": "Active",
"inactive": "Inactive",
"linked": "linked",
"finish": "Finish",
"min": "Min",
"max": "Max",
"avg": "Avg",
"sum": "Sum",
"count": "Count",
"countDistinct": "Count Distinct",
"sumDistinct": "Sum Distinct",
"avgDistinct": "Avg Distinct",
"join": "Join",
"options": "Options",
"primaryValue": "Primary Value",
"useSurveyMode": "Use Survey Mode",
"shift": "Shift",
"enter": "Enter",
"seconds": "Seconds"
},
"objects": {
"workspace": "Workspace",
"workspaces": "Workspaces",
"project": "परिजन",
"projects": "परिजन",
"table": "मज",
@ -95,6 +209,7 @@
"webhooks": "Webhooks",
"view": "रय",
"views": "वि",
"sidebar": "Sidebar",
"viewType": {
"grid": "जल",
"gallery": "गलर",
@ -107,16 +222,27 @@
"users": "उपयगकर",
"role": "भि",
"roles": "भि",
"developer": "Developer",
"roleType": {
"owner": "स",
"creator": "बन",
"editor": "सदक",
"commenter": "टिपणर",
"viewer": "दरशक",
"noaccess": "No Access",
"superAdmin": "Super Admin",
"orgLevelCreator": "Organization Level Creator",
"orgLevelViewer": "Organization Level Viewer"
},
"sqlVIew": "SQL View"
"sqlVIew": "SQL View",
"rowHeight": "Record Height",
"heightClass": {
"short": "Short",
"medium": "Medium",
"tall": "Tall",
"extra": "Extra"
},
"externalDb": "External Database"
},
"datatype": {
"ID": "पहचन",
@ -171,17 +297,63 @@
"isNotNull": "निररथक नह"
},
"title": {
"docs": "Docs",
"forum": "Forum",
"parameter": "Parameter",
"headers": "Headers",
"parameterName": "Parameter Name",
"currencyLocale": "Currency Locale",
"currencyCode": "Currency Code",
"searchMembers": "Search Members",
"noMembersFound": "No members found",
"dateJoined": "Date Joined",
"tokenName": "Token name",
"inDesktop": "in Desktop",
"rowData": "Record data",
"creator": "Creator",
"qrCode": "QR Code",
"termsOfService": "Terms of Service",
"updateSelectedRows": "Update Selected Records",
"noFiltersAdded": "No filters added",
"editCards": "Edit Cards",
"noFieldsFound": "No fields found",
"displayValue": "Display Value",
"expand": "Expand",
"hideAll": "Hide all",
"hideSystemFields": "Hide system fields",
"removeFile": "Remove File",
"hasMany": "Has Many",
"manyToMany": "Many to Many",
"virtualRelation": "Virtual Relation",
"linkMore": "Link More",
"linkMoreRecords": "Link more records",
"downloadFile": "Download File",
"renameTable": "Rename Table",
"renamingTable": "Renaming Table",
"renamingWs": "Renaming Workspace",
"renameWs": "Rename Workspace",
"deleteWs": "Delete Workspace",
"deletingWs": "Deleting Workspace",
"copyAuthToken": "Copy Auth Token",
"copiedAuthToken": "Copied Auth Token",
"copyInviteToken": "Copy Invite Token",
"showSidebar": "Show Sidebar",
"hideSidebar": "Hide Sidebar",
"creatingTable": "Creating Table",
"erdView": "ERD View",
"newBase": "New Data Source",
"newProj": "नयम",
"createBase": "Create Base",
"myProject": "म परिजन",
"formTitle": "परपतर शषक",
"collabView": "सहयमक दय",
"lockedView": "बद दय",
"personalView": "वयकिगत दिण",
"collaborative": "Collaborative",
"locked": "Locked",
"personal": "Personal",
"appStore": "ऐप सर",
"teamAndAuth": "टम और पिक",
"rolesUserMgmt": "भि और उपयगकररबधन",
"userMgmt": "उपयगकररबधन",
"apiTokens": "API Tokens",
"apiTokenMgmt": "एपआई टकन परबधन",
"rolesMgmt": "भिरबधन",
"projMeta": "पट म",
@ -204,20 +376,129 @@
"generateToken": "Generate Token",
"APIsAndSupport": "APIs & Support",
"helpCenter": "Help center",
"noLabels": "No Labels",
"swaggerDocumentation": "Swagger Documentation",
"quickImportFrom": "Quick Import From",
"quickImport": "Quick Import",
"quickImportAirtable": "Quick Import - Airtable",
"quickImportCSV": "Quick Import - CSV",
"quickImportExcel": "Quick Import - Excel",
"quickImportJSON": "Quick Import - JSON",
"jsonEditor": "JSON Editor",
"comingSoon": "Coming Soon",
"advancedSettings": "Advanced Settings",
"codeSnippet": "Code Snippet",
"keyboardShortcut": "Keyboard Shortcuts",
"generateRandomName": "Generate Random Name",
"findRowByScanningCode": "Find row by scanning a QR or Barcode"
"findRowByScanningCode": "Find row by scanning a QR or Barcode",
"tokenManagement": "Token Management",
"addNewToken": "Add new token",
"accountSettings": "Account Settings",
"resetPasswordMenu": "Reset Password",
"tokens": "Tokens",
"userManagement": "User Management",
"accountManagement": "Account management",
"licence": "Licence",
"allowAllMimeTypes": "Allow All Mime Types",
"defaultView": "Default View",
"relations": "Relations",
"switchLanguage": "Switch Language",
"renameFile": "Rename File",
"links": {
"noAction": "No Action",
"cascade": "Cascade",
"restrict": "Restrict",
"setNull": "Set NULL",
"setDefault": "Set Default"
}
},
"labels": {
"heading1": "Heading 1",
"heading2": "Heading 2",
"heading3": "Heading 3",
"bold": "Bold",
"italic": "Italic",
"underline": "Underline",
"strike": "Strike",
"taskList": "Task List",
"bulletList": "Bullet List",
"numberedList": "Numbered List",
"downloadData": "Download Data",
"blockQuote": "Block Quote",
"noToken": "No Token",
"tokenLimit": "Only one token per user is allowed",
"duplicateAttachment": "File with name {filename} already attached",
"viewIdColon": "VIEW ID: {viewId}",
"toAddress": "To Address",
"subject": "Subject",
"body": "Body",
"commaSeparatedMobileNumber": "Comma separated Mobile #",
"headerName": "Header Name",
"icon": "Icon",
"max": "Max",
"enableRichText": "Enable Rich Text",
"idColon": "Id:",
"copiedRecordURL": "Copied Record URL",
"copyRecordURL": "Copy Record URL",
"duplicateRecord": "Duplicate record",
"binaryEncodingFormat": "Binary encoding format",
"syntax": "Syntax",
"examples": "Examples",
"durationInfo": "A duration of time in minutes or seconds (e.g. 1:23).",
"addHeader": "Add Header",
"enterDefaultUrlOptional": "Enter default URL (Optional)",
"negative": "Negative",
"discard": "Discard",
"default": "Default",
"defaultNumberPercent": "Default Number (%)",
"durationFormat": "Duration Format",
"dateFormat": "Date Format",
"timeFormat": "Time Format",
"singularLabel": "Singular Label",
"pluralLabel": "Plural Label",
"optional": "(Optional)",
"clickToMake": "Click to make",
"visibleForRole": "visible for role:",
"inUI": "in UI Dashboard",
"projectSettings": "Base Settings",
"clickToHide": "Click to hide",
"clickToDownload": "Click to download",
"forRole": "for role",
"clickToCopyViewID": "Click to copy View ID",
"viewMode": "View Mode",
"searchUsers": "Search Users",
"superAdmin": "Super Admin",
"allTables": "All Tables",
"members": "Members",
"dataSources": "Data Sources",
"connectDataSource": "Connect a Data Source",
"searchProjects": "Search Bases",
"createdBy": "Created By",
"viewingAttachmentsOf": "Viewing Attachments of",
"readOnly": "Readonly",
"dropHere": "Drop here",
"createdOn": "Created On",
"notifyVia": "Notify Via",
"projName": "परिजनम",
"profile": "Profile",
"accountDetails": "Account Details",
"controlAppearance": "Control your Appearance.",
"accountEmailID": "Account Email ID",
"backToWorkspace": "Back to Workspace",
"untitledToken": "Untitled token",
"tableName": "Table name",
"dashboardName": "Dashboard name",
"createView": "Create a View",
"creatingView": "Creating View",
"duplicateView": "Duplicate View",
"duplicateGridView": "Duplicate Grid View",
"createGridView": "Create Grid View",
"duplicateGalleryView": "Duplicate Gallery View",
"createGalleryView": "Create Gallery View",
"duplicateFormView": "Duplicate Form View",
"createFormView": "Create Form View",
"duplicateKanbanView": "Duplicate Kanban View",
"createKanbanView": "Create Kanban View",
"viewName": "नम द",
"viewLink": "लिक द",
"columnName": "आम नम",
@ -247,6 +528,14 @@
"where": "कह",
"cache": "कश",
"chat": "बत करन",
"showOrHide": "Show or Hide",
"airtable": "Airtable",
"csv": "CSV",
"csvFile": "CSV File",
"json": "JSON",
"jsonFile": "JSON File",
"excel": "Excel",
"microsoftExcel": "Microsoft Excel",
"email": "ईमल",
"storage": "भरण",
"uiAcl": "UI-ACL",
@ -255,6 +544,7 @@
"created": "बन",
"sqlOutput": "SQL आउटपट",
"addOption": "विकलप ज",
"interfaceColor": "Interface Color",
"qrCodeValueColumn": "Column with QR code value",
"barcodeValueColumn": "Column with Barcode value",
"barcodeFormat": "Barcode format",
@ -282,13 +572,17 @@
"joinDiscord": "डिड मिल ह",
"joinCommunity": "NocoDB क समय स",
"joinReddit": "/r/NocoDB म",
"followNocodb": "NocoDB स"
"followNocodb": "NocoDB स",
"communityTranslated": "(Community Translated)"
},
"twitter": "Twitter",
"docReference": "Document Reference",
"selectUserRole": "Select User Role",
"childTable": "Child table",
"childColumn": "Child column",
"childField": "Child field",
"linkToAnotherRecord": "Link to another record",
"links": "Links",
"onUpdate": "On Update",
"onDelete": "On Delete",
"account": "Account",
@ -298,16 +592,21 @@
"customTheme": "Custom Theme",
"requestDataSource": "Request a data source you need?",
"apiKey": "API Key",
"sharedBase": "Shared Base",
"personalAccessToken": "Personal Access Token",
"sharedBaseUrl": "Shared Base URL",
"importData": "Import Data",
"importSecondaryViews": "Import Secondary Views",
"importRollupColumns": "Import Rollup Columns",
"importLookupColumns": "Import Lookup Columns",
"importAttachmentColumns": "Import Attachment Columns",
"importFormulaColumns": "Import Formula Columns",
"importUsers": "Import Users (by email)",
"noData": "No Data",
"goToDashboard": "Go to Dashboard",
"importing": "Importing",
"formatJson": "Format JSON",
"autoSelectFieldTypes": "Auto-Select Field Types",
"firstRowAsHeaders": "Use First Record as Headers",
"flattenNested": "Flatten Nested",
"downloadAllowed": "Download allowed",
"weAreHiring": "We are Hiring!",
@ -325,9 +624,61 @@
"welcomeToNc": "Welcome to NocoDB!",
"inviteOnlySignup": "Allow signup only using invite url",
"nextRow": "Next Row",
"prevRow": "Previous Row"
"prevRow": "Previous Row",
"addRowGrid": "Manually add data in grid view",
"addRowForm": "Enter record data through a form",
"noAccess": "No access",
"restApis": "Rest APIs",
"apis": "APIs",
"includeData": "Include Data",
"includeView": "Include View",
"includeWebhook": "Include Webhook",
"zoomInToViewColumns": "Zoom in to view columns",
"embedInSite": "Embed this view in your site",
"titleRequired": "title is required.",
"sourceNameRequired": "Source name is required",
"changeWsName": "Change Workspace Name",
"pressEnter": "Press Enter",
"newFormLoaded": "New form will be loaded after"
},
"activity": {
"openInANewTab": "Open in a new tab",
"copyIFrameCode": "Copy IFrame code",
"onCondition": "On Condition",
"bulkDownload": "Bulk Download",
"attachFile": "Attach File",
"viewAttachment": "View Attachments",
"attachmentDrop": "Click or drop a file into cell",
"addFiles": "Add File(s)",
"hideInUI": "Hide in UI",
"addBase": "Add Base",
"addParameter": "Add Parameter",
"submitAnotherForm": "Submit Another Form",
"dragAndDropFieldsHereToAdd": "Drag and drop fields here to add",
"editSource": "Edit Data Source",
"enterText": "Enter text",
"okEditBase": "Ok & Edit Base",
"showInUI": "Show in UI",
"outOfSync": "Out of sync",
"newSource": "New Data Source",
"newWebhook": "New Webhook",
"enablePublicAccess": "Enable Public Access",
"doYouWantToSaveTheChanges": "Do you want to save the changes ?",
"editingAccess": "Editing access",
"enabledPublicViewing": "Enable public viewing",
"restrictAccessWithPassword": "Restrict access with password",
"manageProjectAccess": "Manage Base Access",
"allowDownload": "Allow Download",
"surveyMode": "Survey Mode",
"rtlOrientation": "RTL Orientation",
"useTheme": "Use Theme",
"copyLink": "Copy Link",
"copiedLink": "Link Copied",
"copyInviteLink": "Copy invite link",
"copiedInviteLink": "Copied invite link",
"copyUrl": "यआरएल क कर",
"moreColors": "More Colors",
"moveProject": "Move Base",
"createProject": "पट बन",
"importProject": "आयत परिजन",
"searchProject": "खज परिजन",
@ -338,6 +689,7 @@
"deleteProject": "पट हट",
"refreshProject": "तस",
"saveProject": "परिजनरकित कर",
"saveAndQuit": "Save & Quit",
"deleteKanbanStack": "Delete stack?",
"createProjectExtended": {
"extDB": "बहरस स <br> कनट करक बन",
@ -353,6 +705,7 @@
"translate": "अनद करन मदद कर",
"account": {
"authToken": "किक टकन",
"authTokenCopied": "Copied Auth Token",
"swagger": "Swagger: REST APIs",
"projInfo": "कट जनक",
"themes": "विषय"
@ -362,7 +715,10 @@
"filter": "फिटर",
"addFilter": "फिटर ज",
"share": "शयर करन",
"groupBy": "Group By",
"addSubGroup": "Add subgroup",
"shareBase": {
"label": "Share base",
"disable": "स आधर अकषम कर",
"enable": "कई भयकििसकस लिक ह",
"link": "स आधर लिक"
@ -372,6 +728,8 @@
"inviteTeam": "टम क आमित कर",
"inviteUser": "Invite User",
"inviteToken": "टकन क आमित कर",
"linkedRecords": "Linked Records",
"addNewLink": "Add New Link",
"newUser": "नय उपयगकर",
"editUser": "यजर कित कर",
"deleteUser": "परिजन उपयगकरि",
@ -386,8 +744,11 @@
"previousRecord": "पिछलिड",
"copyApiURL": "API URL क कर",
"createTable": "Create New Table",
"createDashboard": "Create Dashboard",
"createWorkspace": "Create Workspace",
"refreshTable": "टबलस रिश",
"renameTable": "Rename Table",
"renameLayout": "Layout Rename",
"deleteTable": "Delete Table",
"addField": "इस ति नयड ज",
"setDisplay": "Set as Display value",
@ -398,6 +759,9 @@
"insertRow": "नई पि",
"duplicateRow": "Duplicate Row",
"deleteRow": "पि हट",
"deleteRows": "Delete records",
"predictColumns": "Predict Fields",
"predictFormulas": "Predict Formulas",
"deleteSelectedRow": "चयनित पि हट",
"importExcel": "आयत एकल",
"importCSV": "Import CSV",
@ -418,6 +782,7 @@
"ListView": "दय स",
"copyView": "परतिििय",
"renameView": "नम बदल",
"uploadData": "Upload Data",
"deleteView": "डिट व",
"createGrid": "गिड व बन",
"createGallery": "गलरय बन",
@ -425,7 +790,6 @@
"createKanban": "कनबन व बन",
"createForm": "फम व बन",
"showSystemFields": "सिटम फड दि",
"copyUrl": "यआरएल क कर",
"openTab": "नयब ख",
"iFrame": "एमबल HTML कड क कर",
"addWebhook": "नयबहक ज",
@ -451,10 +815,24 @@
"addFilterGroup": "Add Filter Group",
"linkRecord": "Link record",
"addNewRecord": "Add new record",
"newRecord": "New record",
"tableNameCreateNewRecord": "{tableName}: Create new record",
"gotSavedLinkedSuccessfully": "{tableName} '{recordTitle}' got saved & linked successfully",
"recordCreatedLinked": "Record Created & Linked",
"useConnectionUrl": "Use Connection URL",
"toggleCommentsDraw": "Toggle comments draw",
"expandRecord": "Expand Record",
"deleteRecord": "Delete Record",
"fullWidth": "Full width",
"exitFullWidth": "Exit full width",
"markAllAsRead": "Mark all as read",
"column": {
"delete": "Delete Field",
"addNumber": "Add Number Field",
"addSingleLineText": "Add SingleLineText Field",
"addLongText": "Add LongText Field",
"addOther": "Add Other Field"
},
"erd": {
"showColumns": "Show Columns",
"showPkAndFk": "Show Primary and Foreign Keys",
@ -475,9 +853,11 @@
"openInGoogleMaps": "Google Maps",
"openInOpenStreetMap": "OSM"
},
"toggleMobileMode": "Toggle Mobile Mode"
"toggleMobileMode": "Toggle Mobile Mode",
"startCommenting": "Start commenting!"
},
"tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment",
"saveChanges": "परिवरतनरकित कर",
"xcDB": "एक नयट बन",
"extDB": "MySQL, PostgreSQL, SQL सरवर और SQLite क समरथन करत",
@ -488,6 +868,7 @@
"light": "क यह कग म आत? (^⇧b)"
},
"addTable": "नई ति",
"addDashboard": "Add new Dashboard",
"inviteMore": "अधिक उपयगकर आमित कर",
"toggleNavDraw": "निशन दरज कगल कर",
"reloadApiToken": "एपआई टकन कड कर",
@ -506,7 +887,19 @@
"clientCA": "सए फइल क चयन कर"
},
"placeholder": {
"selectSlackChannels": "Select Slack channels",
"selectTeamsChannels": "Select Microsoft Teams channels",
"selectDiscordChannels": "Select Discord channels",
"selectMattermostChannels": "Select Mattermost channels",
"webhookTitle": "Webhook Title",
"barcodeColumn": "Select a field for the Barcode value",
"notFoundContent": "No valid field Type can be found.",
"selectBarcodeFormat": "Select a Barcode format",
"projName": "पट नम दरज कर",
"selectGroupField": "Select a Grouping Field",
"selectGroupFieldNotFound": "No Single Select Field can be found. Please create one first.",
"selectGeoField": "Select a GeoData Field",
"selectGeoFieldNotFound": "No GeoData Field can be found. Please create one first.",
"password": {
"enter": "पसवरड दरज कर",
"current": "वरतमन पसवरड",
@ -514,6 +907,8 @@
"save": "पसवरड क बचओ",
"confirm": "नए पसवरड कि कर"
},
"selectAColumnForTheQRCodeValue": "Select a field for the QR code value",
"allowNegativeNumbers": "Allow negative numbers",
"searchProjectTree": "खज टबल",
"searchFields": "खज फड",
"searchColumn": "खज {खज} कलम",
@ -523,19 +918,137 @@
"defaultValue": "डिट मन",
"filterByEmail": "ई-मल दिटर",
"filterQuery": "Filter query",
"selectField": "Select field"
"selectField": "Select field",
"precision": "Precision",
"decimal1": "1.0",
"decimal2": "1.00",
"decimal3": "1.000",
"decimal4": "1.0000",
"decimal5": "1.00000",
"decimal6": "1.000000",
"decimal7": "1.0000000",
"decimal8": "1.00000000",
"value": "Value",
"key": "Key"
},
"msg": {
"clickToCopyFieldId": "Click to copy Field Id",
"enterPassword": "Enter password",
"bySigningUp": "By signing up, you agree to the",
"subscribeToOurWeeklyNewsletter": "Subscribe to our weekly newsletter",
"verifyingPassword": "Verifying Password",
"thisSharedViewIsProtected": "This shared view is protected",
"successfullySubmittedFormData": "Successfully submitted form data",
"formViewNotSupportedOnMobile": "Form view is not supported on mobile",
"newFormWillBeLoaded": "New form will be loaded after {seconds} seconds",
"optimizedQueryDisabled": "Optimized query is disabled",
"optimizedQueryEnabled": "Optimized query is enabled",
"lookupNonBtWarning": "Lookup field is not supported for non-Belongs to relation",
"invalidTime": "Invalid Time",
"linkColumnClearNotSupportedYet": "You don't have any supported links for Lookup",
"recordCouldNotBeFound": "Record could not be found",
"invalidPhoneNumber": "Invalid phone number",
"pageSizeChanged": "Page size changed",
"errorLoadingData": "Error loading data",
"webhookBodyMsg1": "Use context variable",
"webhookBodyMsg2": "body",
"webhookBodyMsg3": "to refer the record under consideration",
"formula": {
"hintStart": "Hint: Use {placeholder1} to reference fields, e.g: {placeholder2}. For more, please check out",
"hintEnd": "Formulas.",
"noSuggestedFormulaFound": "No suggested formula found",
"numericTypeIsExpected": "Numeric type is expected",
"stringTypeIsExpected": "String type is expected",
"operationNotAvailable": "{operation} operation not available",
"cantSaveFieldFormulaInvalid": "Can’t save field because formula is invalid",
"notSupportedToReferenceColumn": "Not supported to reference field {columnName}",
"typeIsExpectedButFound": "Type {type} is expected but found Type {found}",
"requiredArgumentsFormula": "{calleeName} requires {requiredArguments} arguments",
"minRequiredArgumentsFormula": "{calleeName} required minimum {minRequiredArguments} arguments",
"maxRequiredArgumentsFormula": "{calleeName} required maximum {maxRequiredArguments} arguments",
"functionNotAvailable": "{function} function is not available",
"firstParamWeekDayHaveDate": "The first parameter of WEEKDAY() should have date value",
"secondParamWeekDayHaveDate": "The second parameter of WEEKDAY() should have the value either \"sunday\", \"monday\", \"tuesday\", \"wednesday\", \"thursday\", \"friday\" or \"saturday\"",
"firstParamDateAddHaveDate": "The first parameter of DATEADD() should have date value",
"secondParamDateAddHaveNumber": "The second parameter of DATEADD() should have numeric value",
"thirdParamDateAddHaveDate": "The third parameter of DATEADD() should have the value either \"day\", \"week\", \"month\" or \"year\"",
"firstParamDateDiffHaveDate": "The first parameter of DATEDIFF() should have date value",
"secondParamDateDiffHaveDate": "The second parameter of DATEDIFF() should have date value",
"thirdParamDateDiffHaveDate": "The third parameter of DATETIME_DIFF() should have value either \"milliseconds\", \"ms\", \"seconds\", \"s\", \"minutes\", \"m\", \"hours\", \"h\", \"days\", \"d\", \"weeks\", \"w\", \"months\", \"M\", \"quarters\", \"Q\", \"years\", or \"y\"",
"columnNotAvailable": "Field {columnName} is not available",
"cantSaveCircularReference": "Can’t save field because it causes a circular reference",
"columnWithTypeFoundButExpected": "Field {columnName} with {columnType} type is found but {expectedType} type is expected",
"columnNotMatchedWithType": "{columnName} is not matched with {columnType}"
},
"selectOption": {
"cantBeNull": "Select options can't be null",
"multiSelectCantHaveCommas": "MultiSelect fields can't have commas(',')",
"cantHaveDuplicates": "Select options can't have duplicates",
"createNewOptionNamed": "Create new option named"
},
"plsEnterANumber": "Please enter a number",
"plsInputEmail": "Please input email",
"invalidDate": "Invalid date",
"invalidLocale": "Invalid locale",
"invalidCurrencyCode": "Invalid Currency Code",
"postgresHasItsOwnCurrencySettings": "PostgreSQL 'money' type has own currency settings",
"validColumnsForBarCode": "The valid Field Types for a Barcode Field are: Number, Single Line Text, Long Text, Phone Number, URL, Email, Decimal. Please create one first.",
"hm": {
"title": "Has Many Relation",
"tooltip_desc": "A single record from table ",
"tooltip_desc2": " can be linked with multiple records from table "
},
"mm": {
"title": "Many to Many Relation",
"tooltip_desc": "Multiple records from table ",
"tooltip_desc2": " can be linked with multiple records from table "
},
"bt": {
"title": "Belongs to Relation",
"tooltip_desc": "A single record from table ",
"tooltip_desc2": " can be linked with a record from table "
},
"oo": {
"title": "One to One Relation",
"tooltip_desc": "A single record from table ",
"tooltip_desc2": " can be linked with a single record from table "
},
"noRecordsAreLinkedFromTable": "No records are linked from table",
"noRecordsLinked": "No records linked",
"recordsLinked": "records linked",
"acceptOnlyValid": "Accepts only",
"apiTokenCreate": "Create personal API tokens to use in automation or external apps.",
"selectFieldToSort": "Select Field to Sort",
"thereAreNoRecordsInTable": "There are no records in table",
"createWebhookMsg1": "Get started with web-hooks!",
"createWebhookMsg2": "Create web-hooks to power you automations,",
"createWebhookMsg3": "Get notified as soon as there are changes in your data",
"areYouSureUWantTo": "Are you sure you want to delete the following",
"areYouSureUWantToDeleteLabel": "Are you sure you want to {deleteLabel} the following",
"idColumnRequired": "ID field is required, you can rename this later if required.",
"length59Required": "The length exceeds the max 59 characters",
"noNewNotifications": "You have no new notifications",
"noRecordFound": "Record not found",
"rowDeleted": "Record deleted",
"saveChanges": "Do you want to save the changes?",
"tooLargeFieldEntity": "The field is too large to be converted to {entity}",
"roleRequired": "Role required",
"warning": {
"dbValid": "Please make sure database you are trying to connect is valid! This operation can cause schema loss!!",
"barcode": {
"renderError": "Barcode error - please check compatibility between input and barcode type"
},
"nonEditableFields": {
"computedFieldUnableToClear": "Warning: Computed field - unable to clear text",
"qrFieldsCannotBeDirectlyChanged": "Warning: QR fields cannot be directly changed."
}
"qrFieldsCannotBeDirectlyChanged": "Warning: QR fields cannot be directly changed.",
"barcodeFieldsCannotBeDirectlyChanged": "Warning: Barcode fields cannot be directly changed."
},
"duplicateProject": "Are you sure you want to duplicate the base?",
"duplicateTable": "Are you sure you want to duplicate the table?"
},
"info": {
"disabledAsViewLocked": "Disabled as View is locked",
"basesMigrated": "Bases are migrated. Please try again.",
"pasteNotSupported": "Paste operation is not supported on the active cell",
"roles": {
"orgCreator": "Creator can create new projects and access any invited project.",
@ -640,6 +1153,9 @@
"tablesMetadataInSync": "टबल क SYNC ह",
"addMultipleUsers": "आप एकिक COMMA (,) द अलग ईमल जड़ सकत",
"enterTableName": "टबल कम लि",
"enterLayoutName": "Enter Layout name",
"enterDashboardName": "Enter Dashboard name",
"defaultColumns": "Default fields",
"addDefaultColumns": "डिट कलम ज",
"tableNameInDb": "डस मबल कम बच गय",
"airtable": {
@ -662,8 +1178,10 @@
"valueAlreadyInList": "This value is already in the list",
"noColumnsToUpdate": "No columns to update",
"tableDeleted": "Deleted table successfully",
"layoutDeleted": "Deleted layout successfully",
"generatePublicShareableReadonlyBase": "Generate publicly shareable readonly base",
"deleteViewConfirmation": "Are you sure you want to delete this view?",
"deleteLayoutConfirmation": "Are you sure you want to delete this Layout?",
"deleteTableConfirmation": "Do you want to delete the table",
"showM2mTables": "Show M2M Tables",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
@ -674,18 +1192,40 @@
"deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",
"noMoreRecords": "No more records"
"noMoreRecords": "No more records",
"tokenNameNotEmpty": "Token name should not be empty",
"tokenNameMaxLength": "Token name should not be more than 255 characters",
"dbNameRequired": "Database name is required",
"wsNameRequired": "Workspace name required",
"wsNameMinLength": "Workspace name must be at least 3 characters long",
"wsNameMaxLength": "Workspace name must be at most 50 characters long",
"wsDeleteDlg": "Delete this workspace and all it’s contents.",
"userConfirmation": "I understand that this action is irreversible",
"pageNotFound": "Page Not Found",
"makeLineBreak": "to make a line break",
"goToPrevious": "Go to previous",
"goToNext": "Go to next",
"thankYou": "Thank you!",
"submittedFormData": "You have successfully submitted the form data."
},
"error": {
"nameRequired": "Name Required",
"nameMinLength": "Name must be at least 2 characters long",
"nameMaxLength": "Name must be at most 60 characters long",
"viewNameRequired": "View name is required",
"nameMaxLength256": "Name must be at most 256 characters long",
"viewNameUnique": "View name should be unique",
"searchProject": "{search} किए आपकज कई परिम नहि",
"invalidChar": "फडर पथ म अमय चरिर।",
"invalidDbCredentials": "अमय डस कियलस।",
"unableToConnectToDb": "डस स कनट करन असमरथ, कपयच करि आपकस ऊपर ह।",
"invalidYear": "Invalid year",
"userDoesntHaveSufficientPermission": "उपयगकरद नह बनिए परत अनमति।",
"dbConnectionStatus": "अमय डस पटर",
"dbConnectionFailed": "कनशन विफलत:",
"nullFilterExists": "Null filter exists. Please remove them",
"signUpRules": {
"emailReqd": "ईमल क जररत ह",
"emailRequired": "Email is required",
"emailInvalid": "ईमल मय हिए",
"passwdRequired": "पसवरड क आवशयकत",
"passwdLength": "आप पसवरड कम स कम 8 वरण हिए",
@ -695,7 +1235,9 @@
"atLeastOneUppercase": "One Uppercase letter",
"atLeastOneNumber": "One Number",
"atLeastOneSpecialChar": "One special character",
"allowedSpecialCharList": "Allowed special character list"
"allowedSpecialCharList": "Allowed special character list",
"invalidEmails": "Invalid emails",
"invalidEmail": "Invalid Email"
},
"invalidURL": "Invalid URL",
"invalidEmail": "Invalid Email",
@ -726,6 +1268,8 @@
"nameShouldStartWithAnAlphabetOr_": "Name should start with an alphabet or _",
"followingCharactersAreNotAllowed": "Following characters are not allowed",
"columnNameRequired": "Column name is required",
"duplicateColumnName": "Duplicate field name",
"uiDataTypeRequired": "UI data type is required",
"columnNameExceedsCharacters": "The length of column name exceeds the max {value} characters",
"projectNameExceeds50Characters": "Project name exceeds 50 characters",
"projectNameCannotStartWithSpace": "Project name cannot start with space",
@ -758,6 +1302,7 @@
"futureRelease": "जलद आ रह!"
},
"success": {
"licenseKeyUpdated": "License Key Updated",
"columnDuplicated": "Column duplicated successfully",
"rowDuplicatedWithoutSavedYet": "Row duplicated (not saved)",
"updatedUIACL": "Updated UI ACL for tables successfully",
@ -765,6 +1310,7 @@
"pluginSettingsSaved": "Plugin settings saved successfully",
"pluginTested": "Successfully tested plugin settings",
"tableRenamed": "Table renamed successfully",
"layoutRenamed": "Layout renamed successfully",
"viewDeleted": "View deleted successfully",
"primaryColumnUpdated": "Successfully updated as primary column",
"tableDataExported": "Successfully exported all table data",

1016
packages/nc-gui/lang/hr.json

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save