Merge 2024.6-rc branch for release

This commit is contained in:
mathilde-cryptpad 2024-07-02 11:09:03 +02:00
commit febafddc2f
114 changed files with 4643 additions and 8266 deletions

View file

@ -7,6 +7,7 @@ www/components/
www/bower_components/
www/common/onlyoffice/dist
www/common/onlyoffice/x2t
onlyoffice-dist/
www/scratch
www/accounts
@ -15,6 +16,8 @@ www/accounts
www/worker
www/todo
#lib/plugins/
www/common/hyperscript.js
www/pad/wysiwygarea-plugin.js

View file

@ -49,13 +49,10 @@ module.exports = {
// TODO remove these exceptions from the eslint defaults
'no-irregular-whitespace': ['off'],
'no-unused-vars': ['warn'],
'no-self-assign': ['off'],
'no-empty': ['off'],
'no-useless-escape': ['off'],
'no-redeclare': ['off'],
'no-extra-boolean-cast': ['off'],
'no-global-assign': ['off'],
'no-prototype-builtins': ['off'],
}
};

View file

@ -1,60 +0,0 @@
{
"fileExtensions": [".less"],
// These rules are almost certainly crap and will not catch bugs (Caleb)
"newlineAfterBlock": { "enabled": false }, // not just a newline but an entire empty line after each block
"spaceAroundOperator": { "enabled": false }, // disallow calc(10px+10px);
"hexLength": { "enabled": false }, // require long hex color codes or require short where possible
"hexNotation": { "enabled": false }, // require hex lowercase
"propertyOrdering": { "enabled": false }, // require attributes to be in alphabetical order D:
"stringQuotes": { "enabled": false }, // force quoting of strings with ' or " (silly)
"importPath": { "enabled": false }, // require imports to not have .less, ridiculous
"qualifyingElement": { "enabled": false }, // disallow div.xxx and require .xxx
"decimalZero": { "enabled": false }, // disallow .5em
"borderZero": { "enabled": false }, // disallow border: none;
"selectorNaming": { "enabled": false }, // this would be crap because classes are what they are.
"zeroUnit": { "enabled": false },
"singleLinePerProperty": { "enabled": false },
"_singleLinePerProperty": {
"enabled": true,
"allowSingleLineRules": true
},
"spaceAroundComma": { "enabled": false },
"importantRule": { "enabled": false },
"universalSelector": { "enabled": false },
"idSelector": { "enabled": false },
"singleLinePerSelector": { "enabled": false },
"spaceBetweenParens": { "enabled": false },
"maxCharPerLine": { "enabled": false }, // using lesshint flags can cause long lines
"comment": { "enabled": false }, // ban multi-line comments ?
// These rules should be discussed, if they're crap then they should be moved up.
"colorVariables": { "enabled": false }, // require all colors to be stored as variables first...
"variableValue": { "enabled": false }, // any attribute types which should always be variables ? color?
"spaceBeforeBrace": { "enabled": true },//{ "enabled": true, "style": "one_space" },
// Turn everything else on
"spaceAfterPropertyColon": { "enabled": true },
"finalNewline": { "enabled": true }, // require an empty line at the end of the file (enabled for now)
"attributeQuotes": { "enabled": true },
"depthLevel": {
"depth": 1 // TODO(cjd) This is obviously not triggering, even with 1
},
"duplicateProperty": { "enabled": false },
"emptyRule": { "enabled": true },
"hexValidation": { "enabled": true }, // disallow actual garbage color hex codes (e.g. #ab)
"propertyUnits": {
"valid": ["rem", "vw", "em", "px", "ch"], // These units are allowed for all properties
"invalid": ["pt"], // The 'pt' unit is not allowed under any circumstances
"properties": {
//"line-height": [] // No units are allowed for line-height
}
},
"spaceAfterPropertyName": { "enabled": true, "style": "no_space" },
"spaceAfterPropertyValue": { "enabled": true, "style": "no_space" },
"spaceAroundBang": { "enabled": true, "style": "before" },
"trailingSemicolon": { "enabled": true },
"trailingWhitespace": { "enabled": true },
"urlFormat": { "enabled": true, "style": "relative" },
"urlQuotes": { "enabled": true }
}

View file

@ -25,7 +25,7 @@ Files: .jshintrc
Copyright: 2023 XWiki CryptPad Team <contact@cryptpad.org> and contributors
License: AGPL-3.0-or-later
Files: .lesshintrc
Files: .stylelintrc.js
Copyright: 2023 XWiki CryptPad Team <contact@cryptpad.org> and contributors
License: AGPL-3.0-or-later
@ -156,4 +156,4 @@ License: AGPL-3.0-or-later
Files: www/common/onlyoffice/x2t/*
Copyright: Ascensio System Limited 2010-2022
License: AGPL-3.0-or-later
License: AGPL-3.0-or-later

43
.stylelintrc.js Normal file
View file

@ -0,0 +1,43 @@
module.exports = {
"extends": "stylelint-config-standard-less",
"rules": {
"no-descending-specificity": null,
"length-zero-no-unit": null,
"no-duplicate-selectors": null,
"declaration-block-no-duplicate-properties": null,
"comment-empty-line-before": null,
"rule-empty-line-before": null,
"declaration-empty-line-before": null,
"at-rule-empty-line-before": null,
"custom-property-empty-line-before": null,
"font-family-name-quotes": null,
"font-family-no-missing-generic-family-keyword": null,
"declaration-block-no-redundant-longhand-properties": null,
"shorthand-property-no-redundant-values": null,
"declaration-block-no-shorthand-property-overrides": null,
"comment-whitespace-inside": null,
"property-no-vendor-prefix": null,
"selector-no-vendor-prefix": null,
"function-name-case": null,
"selector-class-pattern": null,
"custom-property-pattern": null,
"selector-id-pattern": null,
"selector-pseudo-element-colon-notation": null,
"media-feature-range-notation": null,
"selector-not-notation": null,
"color-function-notation": null,
"alpha-value-notation": null,
"number-max-precision": null,
"at-rule-no-unknown": null, // FIXME
"less/no-duplicate-variables": null,
"less/color-no-invalid-hex": null
}
};

File diff suppressed because it is too large Load diff

View file

@ -22,14 +22,15 @@ RUN npm install --production \
# Create actual CryptPad image
FROM node:lts-slim
ENV DEBIAN_FRONTEND=noninteractive
RUN apt update && apt install -y git rdfind && rm -rf /var/lib/apt/lists/*
# Create user and group for CryptPad so it does not run as root
RUN groupadd cryptpad -g 4001
RUN useradd cryptpad -u 4001 -g 4001 -d /cryptpad
# Install wget for healthcheck
RUN apt-get update && apt-get install --no-install-recommends -y wget && \
# Install curl for healthcheck
# Install git, rdfind and unzip for install-onlyoffice.sh
RUN apt-get update && apt-get install --no-install-recommends -y \
curl ca-certificates git rdfind unzip && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
@ -56,7 +57,7 @@ VOLUME /cryptpad/datastore
ENTRYPOINT ["/bin/bash", "/cryptpad/docker-entrypoint.sh"]
# Healthcheck
HEALTHCHECK --interval=1m CMD wget --no-verbose --tries=1 http://localhost:3000/ -q -O /dev/null || exit 1
HEALTHCHECK --interval=1m CMD curl -f http://localhost:3000/ || exit 1
# Ports
EXPOSE 3000 3003

View file

@ -2,8 +2,6 @@
//
// SPDX-License-Identifier: AGPL-3.0-or-later
/* globals module */
/* DISCLAIMER:
There are two recommended methods of running a CryptPad instance:
@ -89,9 +87,10 @@ module.exports = {
*/
//httpPort: 3000,
/* httpSafePort allows you to specify an alternative port from which
* the node process should serve sandboxed assets. The default value is
* that of your httpPort + 1. You probably don't need to change this.
/* httpSafePort purpose is to emulate another origin for the sandbox when
* you don't have two domains at hand (i.e. when httpSafeOrigin not defined).
* It is meant to be used only in case where you are working on a local
* development instance. The default value is your httpPort + 1.
*
*/
//httpSafePort: 3001,

View file

@ -9,12 +9,14 @@
* If you want to check all the configurable values, you can open the internal configuration file
but you should not change it directly (/common/application_config_internal.js)
*/
define(['/common/application_config_internal.js'], function (AppConfig) {
// Example: If you want to remove the survey link in the menu:
// AppConfig.surveyURL = "";
// To inform users of the support ticket panel which languages your admins speak:
//AppConfig.supportLanguages = [ 'en', 'fr' ];
return AppConfig;
});

View file

@ -22,11 +22,13 @@ define([
'/common/outer/login-block.js',
'/common/common-hash.js',
'/common/outer/http-command.js',
'/api/config',
'/components/tweetnacl/nacl-fast.min.js',
'/components/scrypt-async/scrypt-async.min.js', // better load speed
], function ($, Listmap, Crypto, Util, NetConfig, Login, Cred, ChainPad, Realtime, Constants, UI,
Feedback, h, LocalStore, Messages, nThen, Block, Hash, ServerCommand) {
Feedback, h, LocalStore, Messages, nThen, Block, Hash, ServerCommand,
ApiConfig) {
var Exports = {
Cred: Cred,
Block: Block,
@ -218,6 +220,11 @@ define([
proxy.edPublic = result.edPublic;
}
if (ApiConfig && Array.isArray(ApiConfig.adminKeys) &&
ApiConfig.adminKeys.includes(proxy.edPublic)) {
localStorage.CP_admin = "1";
}
setTimeout(function () {
Realtime.whenRealtimeSyncs(result.realtime, function () {
proceed(result);

View file

@ -14,6 +14,7 @@ var map = {
'fi': 'Suomi',
'fr': 'Français',
//'hi': 'हिन्दी',
'id': 'Bahasa Indonesia',
'it': 'Italiano',
'ja': '日本語',
'nb': 'Norwegian Bokmål',
@ -45,6 +46,7 @@ var getLanguage = Messages._getLanguage = function () {
(map[l.split('_')[0]] ? l.split('_')[0] : 'en'));
};
var language = getLanguage();
window.cryptpadLanguage = language;
// Translations files were migrated from requirejs modules to json.
// To avoid asking every administrator to update their customized translation files,
@ -88,6 +90,9 @@ define(req, function(AppConfig, Default, Language) {
});
}
let html = typeof(document) !== "undefined" && document.documentElement;
if (html) { html.setAttribute('lang', language); }
var extend = function (a, b) {
for (var k in b) {
if (Array.isArray(b[k])) {
@ -129,7 +134,6 @@ define(req, function(AppConfig, Default, Language) {
}
};
return Messages;
});

View file

@ -15,7 +15,8 @@ define([
'/common/outer/local-store.js',
'/customize/pages.js',
'/common/pad-types.js',
], function ($, Config, h, Hash, Constants, Util, TextFit, Msg, AppConfig, LocalStore, Pages, PadTypes) {
'/common/extensions.js'
], function ($, Config, h, Hash, Constants, Util, TextFit, Msg, AppConfig, LocalStore, Pages, PadTypes, Extensions) {
var urlArgs = Config.requireConf.urlArgs;
var checkEarlyAccess = function (x) {
@ -164,9 +165,19 @@ define([
};
let popup = h('div.cp-extensions-popups');
let utils = { h, Util, Hash };
Extensions.getExtensions('HOMEPAGE_POPUP').forEach(ext => {
if (typeof(ext.check) === "function" && !ext.check()) { return; }
ext.getContent(utils, content => {
$(popup).append(h('div.cp-extensions-popup', content));
});
});
return [
h('div#cp-main', [
Pages.infopageTopbar(),
popup,
notice,
h('div.container.cp-container', [
h('div.row.cp-home-hero', [

View file

@ -18,8 +18,6 @@ define([
return;
}
Msg.install_token = "Install token";
document.title = Msg.install_header;
var frame = function (content) {
@ -27,8 +25,7 @@ Msg.install_token = "Install token";
h('div#cp-main', [
//Pages.infopageTopbar(),
h('div.container.cp-container', [
//h('div.row.cp-page-title', h('h1', Msg.install_header)),
h('div.row.cp-page-title', h('h1', Msg.register_header)),
h('div.row.cp-page-title', h('h1', Msg.install_header)),
].concat(content)),
Pages.infopageFooter(),
]),
@ -39,17 +36,12 @@ Msg.install_token = "Install token";
h('div.row.cp-register-det', [
h('div#data.hidden.col-md-6', [
h('h2', Msg.register_notes_title),
//Pages.setHTML(h('div.cp-register-notes'), Msg.install_notes)
Pages.setHTML(h('div.cp-register-notes'), Msg.register_notes)
Pages.setHTML(h('div.cp-register-notes'), Msg.install_notes)
]),
h('div.cp-reg-form.col-md-6', [
h('div#userForm.form-group.hidden', [
h('div.cp-register-instance', [
Msg._getKey('register_instance', [ Pages.Instance.name ]),
/*h('br'),
h('a', {
href: '/features.html'
}, Msg.register_whyRegister)*/
Msg.install_instance,
]),
h('input.form-control#installtoken', {
type: 'text',
@ -75,7 +67,7 @@ Msg.install_token = "Install token";
/*h('div.checkbox-container', [
UI.createCheckbox('import-recent', Msg.register_importRecent, true)
]),*/
h('button#register', Msg.login_register)
h('button#register', Msg.install_launch)
])
]),
])

View file

@ -0,0 +1,98 @@
/*
* SPDX-FileCopyrightText: 2023 XWiki CryptPad Team <contact@cryptpad.org> and contributors
*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@import (reference) "./colortheme-all.less";
@import (reference) "./forms.less";
@import (reference) './icon-colors.less';
.admin_main() {
--LessLoader_require: LessLoader_currentFile();
}
& {
// Instance accent color presets
@palette-colors:
#0087FF,
#de0064,
#8c52bc,
#3d7672;
div.cp-palette-container {
.cp-palette-nocolor {
display: none;
}
.instance-colors(@palette-colors; @index) when (@index > 0) {
// loop through the @colors
.instance-colors(@palette-colors; (@index - 1));
@color: extract(@palette-colors, @index);
// make a numbered class selector for each color
.cp-palette-color@{index} {
background-color: @color !important;
color: contrast(@color, @cryptpad_color_grey_800, @cryptpad_color_grey_200) !important;
}
}
.instance-colors(@palette-colors; length(@palette-colors));
}
.cp-admin-customize-apps-grid, .cp-admin-customize-options-grid {
display: grid;
gap: 0.5rem;
}
.cp-admin-customize-apps-grid {
grid-template-columns: 1fr 1fr 1fr;
.cp-appblock {
padding: 0.5rem;
border-radius: @variables_radius;
font-size: 1.2em;
display: flex;
flex-direction: row;
align-items: center;
gap: 0.75rem;
.iconColors_main();
&:hover {
cursor: pointer;
}
i.cp-icon {
font-size: 2.8rem;
}
.cp-app-name {
flex-grow: 1;
}
}
.cp-inactive-app {
background-color: transparent;
opacity: 0.75;
.cp-on-enabled {
visibility: hidden;
}
}
.cp-active-app {
background-color: fade(@cryptpad_text_col, 10%);
.cp-on-enabled {
visibility: visible;
}
}
}
.cp-admin-customize-options-grid {
grid-template-columns: 1fr 1fr;
.cp-optionblock {
padding: 0.5rem;
border-radius: @variables_radius;
background-color: fade(@cryptpad_text_col, 10%);
align-self: start;
.cp-checkmark-label {
font-weight: bold;
}
.cp-option-hint {
margin-left: 30px;
display: inline-block;
}
}
}
}

View file

@ -198,6 +198,12 @@
text-decoration: none;
}
}
.cp-usergrid-user, textarea, a, .fa-times {
outline: none;
&:focus {
outline: @cryptpad_color_brand solid 2px;
}
}
}
.cp-alertify-type-container {
overflow: visible !important;
@ -237,6 +243,10 @@
}
}
}
outline: none;
&:focus {
outline: @cryptpad_color_brand solid 2px;
}
}
span.alertify-tabs-active {
background-color: @cp_alertify-fg !important;
@ -263,6 +273,10 @@
input {
.tools_placeholder-color();
outline: none;
&:focus-visible {
outline: @cryptpad_color_brand solid 2px;
}
}
span.cp-password-container {

View file

@ -128,9 +128,9 @@
position: absolute;
box-sizing: border-box;
}
outline: none;
&:focus {
box-shadow: 0px 0px 5px @cp_checkmark-back1;
outline: none;
outline: @cryptpad_color_brand solid 2px;
}
}
@ -216,9 +216,9 @@
height: @checkmark-dim1;
height: var(--checkmark-dim1);
}
outline: none;
&:focus {
box-shadow: 0px 0px 5px @cp_checkmark-back1;
outline: none;
outline: @cryptpad_color_brand solid 2px;
}
}

View file

@ -119,10 +119,34 @@
}
}
// The following palette container is just for the UI components
// The specific colors you want to show have to be defined in your app
// using the classes .cp-palette-nocolor .cp-palette-color1 .cp-palette-color2 etc.
div.cp-palette-container {
display: flex;
justify-content: space-between;
.cp-palette-color {
display: inline-block;
border-radius: 50%;
height: 30px;
width: 30px;
text-align: center;
line-height: 30px;
color: @cp_kanban-fg;
border: 1px solid fade(@cp_kanban-fg, 40%);
&.fa-check { // tick on selected color
color: @cryptpad_text_col;
}
outline: none;
&:focus {
outline: @cryptpad_color_brand solid 2px;
}
}
}
button.btn {
background-color: @cp_buttons-cancel;
box-sizing: border-box;
outline: 0;
align-items: center;
padding: 0 6px;
line-height: 36px;
@ -232,11 +256,9 @@
}
outline: none;
&:focus {
//border: 1px dotted @alertify-base;
box-shadow: 0px 0px 5px @cp_buttons-primary !important;
outline: none;
outline: @cryptpad_color_brand solid 2px;
}
&::-moz-focus-inner {
border: 0;

View file

@ -36,9 +36,6 @@
}
.cp-reminder, .cp-avatar {
cursor: pointer;
&:hover {
background-color: @cp_dropdown-bg-hover;
}
}
.cp-avatar {
.avatar_main(30px);
@ -61,9 +58,6 @@
}
&.cp-clickable {
cursor: pointer;
&:hover {
background-color: @cp_dropdown-bg-hover;
}
}
}
.cp-notification-dismiss {
@ -73,9 +67,6 @@
align-items: center;
justify-content: center;
cursor: pointer;
&:hover {
background-color: @cp_dropdown-bg-hover;
}
}
}
}

View file

@ -80,6 +80,10 @@
text-overflow: ellipsis;
padding-left: 4px;
vertical-align: middle;
outline: none;
&:focus {
outline: @cryptpad_color_brand solid 2px;
}
}
.close {
opacity: 1;

View file

@ -77,6 +77,12 @@
&:hover {
background-color: contrast(@cp_toolbar-bg, darken(@cp_toolbar-bg, 5%), lighten(@cp_toolbar-bg, 5%));
}
&:focus {
outline: @cryptpad_color_brand solid 2px;
}
}
button:nth-of-type(1) {
margin-left: 0.3rem;
}
}
@ -774,7 +780,7 @@
padding: 10px;
color: @toolbar-bg-color;
color: var(--toolbar-bg-color);
border-radius: 5px;
border-radius: @variables_radius;
span {
font-size: 45px;

View file

@ -115,7 +115,8 @@
}
}
.fa-times {
padding-left: 5px;
border-radius: @variables_radius;
margin-left: 5px;
cursor: pointer;
height: 100%;
line-height: 25px;

View file

@ -297,6 +297,29 @@
}
}
.cp-extensions-popups {
width: 100%;
.cp-extensions-popup {
background-color: @cp_alertify-bg;
border-radius: @infopages-radius-L;
padding: 10px;
box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.2);
width: 400px;
max-width: 100%;
color: @cryptpad_text_col;
margin-left: 40px;
}
}
@media (max-width: 700px) {
.cp-extensions-popups {
max-width: 90%;
.cp-extensions-popup {
margin-left: 0;
}
}
}
@media (min-width: 576px) and (max-width: 767px) {
.container {
padding-left: 0;

View file

@ -0,0 +1,18 @@
// SPDX-FileCopyrightText: 2023 XWiki CryptPad Team <contact@cryptpad.org> and contributors
//
// SPDX-License-Identifier: AGPL-3.0-or-later
/*
* You can override the translation text using this file.
* The recommended method is to make a copy of this file (/customize.dist/translations/messages.{LANG}.js)
in a 'customize' directory (/customize/translations/messages.{LANG}.js).
* If you want to check all the existing translation keys, you can open the internal language file
but you should not change it directly (/common/translations/messages.{LANG}.js)
*/
define(['/common/translations/messages.id.js'], function (Messages) {
// Replace the existing keys in your copied file here:
// Messages.button_newpad = "New Rich Text Document";
return Messages;
});

View file

@ -3,11 +3,9 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
---
version: '3.8'
services:
cryptpad:
image: "cryptpad/cryptpad:version-2024.3.1"
image: "cryptpad/cryptpad:version-2024.6.0"
hostname: cryptpad
environment:

View file

@ -9,11 +9,13 @@
# in production and require professional support please contact sales@cryptpad.fr
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
# Let's Encrypt webroot
include letsencrypt-webroot;
# Include mime.types to be able to support .mjs files (see "types" below)
include mime.types;
@ -82,6 +84,9 @@ server {
# replace with the IP address of your resolver
resolver 8.8.8.8 8.8.4.4 1.1.1.1 1.0.0.1 9.9.9.9 149.112.112.112 208.67.222.222 208.67.220.220;
# OnlyOffice fonts may be loaded from both domains
if ($uri ~ ^\/common\/onlyoffice\/.*\/fonts\/.*$) { set $allowed_origins "*"; }
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options nosniff;
add_header Access-Control-Allow-Origin "${allowed_origins}";
@ -229,6 +234,20 @@ server {
add_header Cross-Origin-Embedder-Policy require-corp;
}
location ~ ^/extensions.js {
proxy_pass http://localhost:3000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# These settings prevent both NGINX and the API server
# from setting the same headers and creating duplicates
proxy_hide_header Cross-Origin-Resource-Policy;
add_header Cross-Origin-Resource-Policy cross-origin;
proxy_hide_header Cross-Origin-Embedder-Policy;
add_header Cross-Origin-Embedder-Policy require-corp;
}
# Requests for blobs and blocks are now proxied to the API server
# This simplifies NGINX path configuration in the event they are being hosted in a non-standard location
# or with odd unexpected permissions. Serving blobs in this manner also means that it will be possible to

View file

@ -40,7 +40,7 @@ SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"
ProxyPassReverse http://localhost:3000/
</Location>
<Location "/cryptpad_websocket">
ProxyPassMatch http://localhost:3003/ upgrade=websocket
ProxyPass http://localhost:3003/ upgrade=websocket
ProxyPassReverse http://localhost:3003/
</Location>
</VirtualHost>

View file

@ -9,8 +9,9 @@
# in production and require professional support please contact sales@cryptpad.fr
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
# Let's Encrypt webroot
include letsencrypt-webroot;

View file

@ -6,7 +6,7 @@
set -euo pipefail
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
CONF_DIR=$SCRIPT_DIR/onlyoffice-conf
BUILDS_DIR=$CONF_DIR/onlyoffice-builds.git
OO_DIR=$SCRIPT_DIR/www/common/onlyoffice/dist
@ -14,85 +14,89 @@ PROPS_FILE="$CONF_DIR"/onlyoffice.properties
declare -A PROPS
main () {
mkdir -p "$CONF_DIR"
main() {
mkdir -p "$CONF_DIR"
load_props
load_props
parse_arguments "$@"
parse_arguments "$@"
ask_for_license
ask_for_license
# Remeber the 1st version that is installed. This will help us install only
# needed OnlyOffice versions in a later version of this script.
set_prop oldest_needed_version v1
# Remeber the 1st version that is installed. This will help us install only
# needed OnlyOffice versions in a later version of this script.
set_prop oldest_needed_version v1
mkdir -p "$OO_DIR"
install_version v1 4f370beb
install_version v2b d9da72fd
install_version v4 6ebc6938
install_version v5 88a356f0
install_version v6 abd8a309
install_version v7 ba82142f
mkdir -p "$OO_DIR"
install_version v1 4f370beb
install_version v2b d9da72fd
install_version v4 6ebc6938
install_version v5 88a356f0
install_version v6 abd8a309
install_version v7 ba82142f
install_x2t v7.3+1 ab0c05b0e4c81071acea83f0c6a8e75f5870c360ec4abc4af09105dd9b52264af9711ec0b7020e87095193ac9b6e20305e446f2321a541f743626a598e5318c1
rm -rf "$BUILDS_DIR"
if command -v rdfind &> /dev/null; then
rdfind -makehardlinks true -makeresultsfile false $OO_DIR/v*
fi
rm -rf "$BUILDS_DIR"
if command -v rdfind &>/dev/null; then
rdfind -makehardlinks true -makeresultsfile false $OO_DIR/v*
fi
}
load_props () {
if [ -e "$PROPS_FILE" ]; then
while IFS='=' read -r key value; do
PROPS["$key"]="$value"
done < "$PROPS_FILE"
fi
load_props() {
if [ -e "$PROPS_FILE" ]; then
while IFS='=' read -r key value; do
PROPS["$key"]="$value"
done <"$PROPS_FILE"
fi
}
set_prop () {
PROPS["$1"]="$2"
set_prop() {
PROPS["$1"]="$2"
for i in "${!PROPS[@]}"; do
echo "$i=${PROPS[$i]}"
done > "$PROPS_FILE"
for i in "${!PROPS[@]}"; do
echo "$i=${PROPS[$i]}"
done >"$PROPS_FILE"
}
parse_arguments () {
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
show_help
shift
;;
-a|--accept-license)
ACCEPT_LICENSE="1"
shift
;;
*)
show_help
shift
;;
esac
done
parse_arguments() {
while [[ $# -gt 0 ]]; do
case $1 in
-h | --help)
show_help
shift
;;
-a | --accept-license)
ACCEPT_LICENSE="1"
shift
;;
*)
show_help
shift
;;
esac
done
}
ask_for_license () {
if [ ${ACCEPT_LICENSE+x} ] || [ "${PROPS[agree_license]:-no}" == yes ]; then
return
fi
ask_for_license() {
if [ ${ACCEPT_LICENSE+x} ] || [ "${PROPS[agree_license]:-no}" == yes ]; then
return
fi
ensure_command_available curl
ensure_command_available curl
(echo -e "Please review the license of OnlyOffice:\n\n" ; curl https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/LICENSE.txt 2>/dev/null) | less
(
echo -e "Please review the license of OnlyOffice:\n\n"
curl https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/LICENSE.txt 2>/dev/null
) | less
read -rp "Do you accept the license? (Y/N): " confirm \
&& [[ $confirm == [yY] || $confirm == [yY][eE][sS] ]] || exit 1
read -rp "Do you accept the license? (Y/N): " confirm &&
[[ $confirm == [yY] || $confirm == [yY][eE][sS] ]] || exit 1
set_prop "agree_license" yes
set_prop "agree_license" yes
}
show_help () {
cat << EOF
show_help() {
cat <<EOF
install-onlyoffice installs or upgrades OnlyOffice.
NOTE: When you have rdfind installed, it will be used to save ~650MB of disk
@ -107,53 +111,87 @@ OPTIONS:
script. Read and accept this before using this option:
https://github.com/ONLYOFFICE/web-apps/blob/master/LICENSE.txt
EOF
exit 1
exit 1
}
ensure_oo_is_downloaded () {
ensure_command_available git
ensure_oo_is_downloaded() {
ensure_command_available git
if ! [ -d "$BUILDS_DIR" ]; then
echo "Downloading OnlyOffice..."
git clone --bare https://github.com/cryptpad/onlyoffice-builds.git "$BUILDS_DIR"
fi
if ! [ -d "$BUILDS_DIR" ]; then
echo "Downloading OnlyOffice..."
git clone --bare https://github.com/cryptpad/onlyoffice-builds.git "$BUILDS_DIR"
fi
}
install_version () {
local DIR=$1
local COMMIT=$2
local FULL_DIR=$OO_DIR/$DIR
local LAST_DIR
LAST_DIR=$(pwd)
install_version() {
local DIR=$1
local COMMIT=$2
local FULL_DIR=$OO_DIR/$DIR
local LAST_DIR
LAST_DIR=$(pwd)
if [ ! -e "$FULL_DIR"/.commit ] || [ "$(cat "$FULL_DIR"/.commit)" != "$COMMIT" ]; then
ensure_oo_is_downloaded
if [ ! -e "$FULL_DIR"/.commit ] || [ "$(cat "$FULL_DIR"/.commit)" != "$COMMIT" ]; then
ensure_oo_is_downloaded
rm -rf "$FULL_DIR"
rm -rf "$FULL_DIR"
cd "$BUILDS_DIR"
git worktree add "$FULL_DIR" "$COMMIT"
cd "$BUILDS_DIR"
git worktree add "$FULL_DIR" "$COMMIT"
cd "$LAST_DIR"
cd "$LAST_DIR"
echo "$COMMIT" > "$FULL_DIR"/.commit
echo "$COMMIT" >"$FULL_DIR"/.commit
echo "$DIR updated"
else
echo "$DIR was up to date"
fi
echo "$DIR updated"
else
echo "$DIR was up to date"
fi
if [ ${CLEAR+x} ]; then
rm -f "$FULL_DIR"/.git
fi
if [ ${CLEAR+x} ]; then
rm -f "$FULL_DIR"/.git
fi
}
ensure_command_available () {
if ! command -v "$1" &> /dev/null; then
echo "$1 needs to be installed to run this script"
exit 1
fi
install_x2t() {
ensure_command_available curl
ensure_command_available sha512sum
ensure_command_available unzip
local VERSION=$1
local HASH=$2
local LAST_DIR
LAST_DIR=$(pwd)
local X2T_DIR=$OO_DIR/x2t
if [ ! -e "$X2T_DIR"/.version ] || [ "$(cat "$X2T_DIR"/.version)" != "$VERSION" ]; then
rm -rf "$X2T_DIR"
mkdir -p "$X2T_DIR"
cd "$X2T_DIR"
curl "https://github.com/cryptpad/onlyoffice-x2t-wasm/releases/download/$VERSION/x2t.zip" --location --output x2t.zip
# curl "https://github.com/cryptpad/onlyoffice-x2t-wasm/releases/download/v7.3%2B1/x2t.zip" --location --output x2t.zip
echo "$HASH x2t.zip" >x2t.zip.sha512
if ! sha512sum --check x2t.zip.sha512; then
echo "x2t.zip does not match expected checksum"
exit 1
fi
unzip x2t.zip
rm x2t.zip*
echo "$VERSION" >"$X2T_DIR"/.version
echo "x2t updated"
else
echo "x2t was up to date"
fi
}
ensure_command_available() {
if ! command -v "$1" &>/dev/null; then
echo "$1 needs to be installed to run this script"
exit 1
fi
}
main "$@"

View file

@ -8,8 +8,10 @@ const Decrees = require("./decrees");
const nThen = require("nthen");
const Fs = require("fs");
const Fse = require("fs-extra");
const Path = require("path");
const Nacl = require("tweetnacl/nacl-fast");
const Hash = require('./common-hash');
module.exports.create = function (Env) {
var log = Env.Log;
@ -25,6 +27,41 @@ nThen(function (w) {
console.error(err);
}
}));
}).nThen(function (w) {
let admins = Env.admins || [];
// If we don't have any admin on this instance, print an onboarding link
if (Array.isArray(admins) && admins.length) { return; }
let token = Env.installToken;
let printLink = () => {
let url = `${Env.httpUnsafeOrigin}/install/#${token}`;
console.log('=============================');
console.log('Create your first admin account and customize your instance by visiting');
console.log(url);
console.log('=============================');
};
// If we already have a token, print it
if (token) { return void printLink(); }
// Otherwise create a new token
let decreeName = Path.join(Env.paths.decree, 'decree.ndjson');
token = Hash.createChannelId() + Hash.createChannelId();
let decree = ["ADD_INSTALL_TOKEN",[token],"",+new Date()];
Fs.appendFile(decreeName, JSON.stringify(decree) + '\n', w(function (err) {
if (err) { console.log(err); return; }
Env.installToken = token;
Env.envUpdated.fire();
printLink();
}));
}).nThen(function () {
if (!Env.admins.length) {
Env.Log.info('NO_ADMIN_CONFIGURED', {
message: `Your instance is not correctly configured for production usage. Review its checkup page for more information.`,
details: new URL('/checkup/', Env.httpUnsafeOrigin).href,
});
}
}).nThen(function (w) {
// we assume the server has generated a secret used to validate JWT tokens
if (typeof(Env.bearerSecret) === 'string') { return; }
@ -40,9 +77,19 @@ nThen(function (w) {
], w(function (err) {
if (err) { throw err; }
}));
}).nThen(function (w) {
Fse.mkdirp(Env.paths.block, w(function (err) {
if (err) {
log.error("BLOCK_FOLDER_CREATE_FAILED", err);
}
}));
}).nThen(function (w) {
var fullPath = Path.join(Env.paths.block, 'placeholder.txt');
Fs.writeFile(fullPath, 'PLACEHOLDER\n', w());
Fs.writeFile(fullPath, 'PLACEHOLDER\n', w(function (err) {
if (err) {
log.error('BLOCK_PLACEHOLDER_CREATE_FAILED', err);
}
}));
}).nThen(function () {
// asynchronously create a historyKeeper and RPC together
require('./historyKeeper.js').create(Env, function (err, historyKeeper) {

View file

@ -2,7 +2,6 @@
//
// SPDX-License-Identifier: AGPL-3.0-or-later
/* globals Buffer */
const B32 = require("thirty-two");
const OTP = require("notp");
const nThen = require("nthen");

View file

@ -2,7 +2,6 @@
//
// SPDX-License-Identifier: AGPL-3.0-or-later
/* globals process */
const nThen = require("nthen");
const getFolderSize = require("get-folder-size");
const Util = require("../common-util");
@ -492,6 +491,8 @@ var setLastEviction = function (Env, Server, cb, data, unsafeKey) {
// CryptPad_AsyncStore.rpc.send('ADMIN', ['INSTANCE_STATUS], console.log)
var instanceStatus = function (Env, Server, cb) {
cb(void 0, {
appsToDisable: Env.appsToDisable,
restrictRegistration: Env.restrictRegistration,
restrictSsoRegistration: Env.restrictSsoRegistration,
dontStoreSSOUsers: Env.dontStoreSSOUsers,

View file

@ -2,7 +2,6 @@
//
// SPDX-License-Identifier: AGPL-3.0-or-later
/* globals Buffer*/
const Block = module.exports;
const Nacl = require("tweetnacl/nacl-fast");
const nThen = require("nthen");

View file

@ -2,7 +2,6 @@
//
// SPDX-License-Identifier: AGPL-3.0-or-later
/* globals process */
const Core = module.exports;
const Util = require("../common-util");
const escapeKeyCharacters = Util.escapeKeyCharacters;

View file

@ -2,7 +2,6 @@
//
// SPDX-License-Identifier: AGPL-3.0-or-later
/* globals Buffer*/
const Quota = module.exports;
//const Util = require("../common-util");

6
lib/common-hash.js Normal file
View file

@ -0,0 +1,6 @@
// SPDX-FileCopyrightText: 2023 XWiki CryptPad Team <contact@cryptpad.org> and contributors
//
// SPDX-License-Identifier: AGPL-3.0-or-later
module.exports = require("../www/common/common-hash");

View file

@ -169,6 +169,7 @@ var isInteger = function (n) {
var args_isString = function (args) {
return !(!Array.isArray(args) || !isString(args[0]));
};
var args_isInteger = function (args) {
return !(!Array.isArray(args) || !isInteger(args[0]));
};
@ -211,10 +212,6 @@ commands.SET_ARCHIVE_RETENTION_TIME = makeIntegerSetter('archiveRetentionTime');
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_ACCOUNT_RETENTION_TIME', [365]]], console.log)
commands.SET_ACCOUNT_RETENTION_TIME = makeIntegerSetter('accountRetentionTime');
var args_isString = function (args) {
return Array.isArray(args) && typeof(args[0]) === "string";
};
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_ADMIN_EMAIL', ['admin@website.tld']]], console.log)
commands.SET_ADMIN_EMAIL = makeGenericSetter('adminEmail', args_isString);
@ -223,6 +220,15 @@ commands.SET_SUPPORT_MAILBOX = makeGenericSetter('supportMailbox', function (arg
return args_isString(args) && Core.isValidPublicKey(args[0]);
});
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_SUPPORT_KEYS', ["Tdz6+fE9N9XXBY93rW5qeNa/k27yd40c0vq7EJyt7jA=", "Tdz6+fE9N9XXBY93rW5qeNa/k27yd40c0vq7EJyt7jA="]]], console.log)
commands.DISABLE_APPS = function (Env, args) {
if (!Array.isArray(args)) { throw new Error("INVALID_ARGS"); }
if (JSON.stringify(args) === JSON.stringify(Env.appsToDisable)) { return false; }
Env.appsToDisable = args;
return true;
};
commands.SET_SUPPORT_KEYS = function (Env, args) {
const curvePublic = args[0]; // Support mailbox key
const edPublic = args[1]; // Support pin log
@ -235,7 +241,7 @@ commands.SET_SUPPORT_KEYS = function (Env, args) {
Env.supportMailboxKey = curvePublic;
Env.supportPinKey = edPublic;
return true;
};
};
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_INSTANCE_PURPOSE', ["development"]]], console.log)
commands.SET_INSTANCE_PURPOSE = makeGenericSetter('instancePurpose', args_isString);
@ -293,7 +299,7 @@ var args_isMaintenance = function (args) {
// whenever that happens we can relax validation a bit to support more formats
var makeBroadcastSetter = function (attr, validation) {
return function (Env, args) {
if ((validation && !validation(args)) && !args_isString(args)) {
if ((validation && !validation(args)) && !args_isString(args)) {
throw new Error('INVALID_ARGS');
}
var str = args[0];

View file

@ -2,8 +2,6 @@
//
// SPDX-License-Identifier: AGPL-3.0-or-later
/* globals process */
const { existsSync, readdirSync } = require('node:fs');
const Crypto = require('crypto');

View file

@ -2,7 +2,6 @@
//
// SPDX-License-Identifier: AGPL-3.0-or-later
/* global Buffer */
var HK = module.exports;
const nThen = require('nthen');

View file

@ -78,15 +78,26 @@ COMMANDS.TOTP_REVOKE = TOTP.TOTP_REVOKE;
COMMANDS.TOTP_WRITE_BLOCK = TOTP.TOTP_WRITE_BLOCK; // Password change only for now (v5.5.0)
COMMANDS.TOTP_REMOVE_BLOCK = TOTP.TOTP_REMOVE_BLOCK;
try {
// SSO plugin may not be installed
const SSO = plugins.SSO && plugins.SSO.challenge;
COMMANDS.SSO_AUTH = SSO.SSO_AUTH;
COMMANDS.SSO_AUTH_CB = SSO.SSO_AUTH_CB;
COMMANDS.SSO_WRITE_BLOCK = SSO.SSO_WRITE_BLOCK; // Account creation only
COMMANDS.SSO_UPDATE_BLOCK = SSO.SSO_UPDATE_BLOCK; // Password change
COMMANDS.SSO_VALIDATE = SSO.SSO_VALIDATE;
} catch (e) {}
// Load challenges added by plugins
Object.keys(plugins || {}).forEach(id => {
try {
let plugin = plugins[id];
if (!plugin.challenge) { return; }
let commands = plugin.challenge;
Object.keys(commands).forEach(cmd => {
if (COMMANDS[cmd]) { return; } // Don't overwrite
COMMANDS[cmd] = commands[cmd];
});
} catch (e) {}
});
/*
const SSO = plugins.SSO && plugins.SSO.challenge;
COMMANDS.SSO_AUTH = SSO.SSO_AUTH;
COMMANDS.SSO_AUTH_CB = SSO.SSO_AUTH_CB;
COMMANDS.SSO_WRITE_BLOCK = SSO.SSO_WRITE_BLOCK; // Account creation only
COMMANDS.SSO_UPDATE_BLOCK = SSO.SSO_UPDATE_BLOCK; // Password change
COMMANDS.SSO_VALIDATE = SSO.SSO_VALIDATE;
*/
var randomToken = () => Nacl.util.encodeBase64(Nacl.randomBytes(24)).replace(/\//g, '-');

View file

@ -161,6 +161,13 @@ var setHeaders = function (req, res) {
}
var h = getHeaders(Env, type);
// Allow main domain to load resources from the sandbox URL
if (!Env.enableEmbedding && req.get('origin') === Env.httpUnsafeOrigin &&
/^\/common\/onlyoffice\/dist\/.*\/fonts\/.*/.test(req.url)) {
h['Access-Control-Allow-Origin'] = Env.httpUnsafeOrigin;
}
applyHeaderMap(res, h);
};
@ -506,6 +513,11 @@ app.use("/block", (req, res, next) => {
next();
});
Object.keys(plugins || {}).forEach(name => {
let plugin = plugins[name];
if (!plugin.addHttpEndpoints) { return; }
plugin.addHttpEndpoints(Env, app);
});
app.use("/customize", Express.static('customize'));
app.use("/customize", Express.static('customize.dist'));
@ -583,6 +595,7 @@ var serveConfig = makeRouteCache(function () {
maxUploadSize: Env.maxUploadSize,
premiumUploadSize: Env.premiumUploadSize,
restrictRegistration: Env.restrictRegistration,
appsToDisable: Env.appsToDisable,
restrictSsoRegistration: Env.restrictSsoRegistration,
httpSafeOrigin: Env.httpSafeOrigin,
enableEmbedding: Env.enableEmbedding,
@ -618,6 +631,35 @@ var serveBroadcast = makeRouteCache(function () {
app.get('/api/config', serveConfig);
app.get('/api/broadcast', serveBroadcast);
(function () {
let extensions = plugins._extensions;
let styles = plugins._styles;
let str = JSON.stringify(extensions);
let str2 = JSON.stringify(styles);
let js = `let extensions = ${str};
let styles = ${str2};
let lang = window.cryptpadLanguage;
let paths = [];
extensions.forEach(name => {
paths.push(\`optional!/\${name}/extensions.js\`);
paths.push(\`optional!json!/\${name}/translations/messages.json\`);
paths.push(\`optional!json!/\${name}/translations/messages.\${lang}.json\`);
});
styles.forEach(name => {
paths.push(\`optional!less!/\${name}/style.less\`);
});
define(paths, function () {
let args = Array.prototype.slice.apply(arguments);
return args;
}, function () {
// ignore missing files
});`;
app.get('/extensions.js', (req, res) => {
res.setHeader('Content-Type', 'text/javascript');
res.send(js);
});
})();
var Define = function (obj) {
return `define(function (){
return ${JSON.stringify(obj, null, '\t')};
@ -711,7 +753,7 @@ app.post('/api/auth', function (req, res, next) {
});
app.use(function (req, res /*, next */) {
if (/^(\/favicon\.ico\/|.*\.js\.map)$/.test(req.url)) {
if (/^(\/favicon\.ico\/|.*\.js\.map|.*\/translations\/.*\.json)/.test(req.url)) {
// ignore common 404s
} else {
Log.info('HTTP_404', req.url);

View file

@ -39,8 +39,6 @@ var handlers = {};
handlers[level] = function (ctx, content) { console.error(content); };
});
var noop = function () {};
var createLogType = function (ctx, type) {
if (logLevels.indexOf(type) < logLevels.indexOf(ctx.logLevel)) {
return noop;

View file

@ -4,6 +4,8 @@
const fs = require('node:fs');
const plugins = {};
const extensions = plugins._extensions = [];
const styles = plugins._styles = [];
try {
let pluginsDir = fs.readdirSync(__dirname + '/plugins');
@ -12,6 +14,18 @@ try {
try {
let plugin = require(`./plugins/${name}/index`);
plugins[plugin.name] = plugin.modules;
try {
let hasExt = fs.existsSync(`lib/plugins/${name}/client/extensions.js`);
if (hasExt) {
extensions.push(plugin.name.toLowerCase());
}
} catch (e) {}
try {
let hasStyle = fs.existsSync(`lib/plugins/${name}/client/style.less`);
if (hasStyle) {
styles.push(plugin.name.toLowerCase());
}
} catch (e) {}
} catch (err) {
console.error(err);
}

View file

@ -83,7 +83,6 @@ Stats.instanceData = function (Env) {
data.providesAggregateStatistics = true;
data.statistics = {}; // Filled in lib/commands/quota.js because of async calls
}
return data;
};

View file

@ -2,7 +2,6 @@
//
// SPDX-License-Identifier: AGPL-3.0-or-later
/* globals Buffer */
var Fs = require("fs");
var Fse = require("fs-extra");
var Path = require("path");

View file

@ -3,7 +3,6 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
/*@flow*/
/* globals Buffer */
var Fs = require("fs");
var Fse = require("fs-extra");
var Path = require("path");

View file

@ -2,8 +2,6 @@
//
// SPDX-License-Identifier: AGPL-3.0-or-later
/* global Buffer */
const ToPull = require('stream-to-pull-stream');
const Pull = require('pull-stream');

View file

@ -2,8 +2,6 @@
//
// SPDX-License-Identifier: AGPL-3.0-or-later
/* globals process, Buffer */
const HK = require("../hk-util");
const Store = require("../storage/file");
const BlobStore = require("../storage/blob");

View file

@ -2,7 +2,6 @@
//
// SPDX-License-Identifier: AGPL-3.0-or-later
/* global process */
const Util = require("../common-util");
const nThen = require('nthen');
const OS = require("os");

2580
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
{
"name": "cryptpad",
"description": "realtime collaborative visual editor with zero knowledge server",
"version": "2024.3.1",
"description": "a collaborative office suite that is end-to-end encrypted and open-source",
"version": "2024.6.0",
"license": "AGPL-3.0+",
"repository": {
"type": "git",
@ -20,8 +20,8 @@
"bootstrap-tokenfield": "^0.12.0",
"chainpad": "^5.2.6",
"chainpad-crypto": "^0.2.5",
"chainpad-listmap": "^1.0.0",
"chainpad-netflux": "^1.0.0",
"chainpad-listmap": "^1.1.0",
"chainpad-netflux": "^1.2.0",
"chainpad-server": "^5.2.0",
"ckeditor": "npm:ckeditor4@~4.22.1",
"codemirror": "^5.19.0",
@ -44,7 +44,7 @@
"localforage": "^1.5.2",
"marked": "^4.3.0",
"mathjax": "3.0.5",
"netflux-websocket": "^1.0.0",
"netflux-websocket": "^1.2.0",
"notp": "^2.0.3",
"nthen": "0.1.8",
"open-sans-fontface": "^1.4.0",
@ -63,19 +63,19 @@
"thirty-two": "^1.0.2",
"tweetnacl": "~0.12.2",
"ulimit": "0.0.2",
"ws": "^3.3.1",
"ws": "^8.17.1",
"x2js": "^3.4.4"
},
"devDependencies": {
"eslint": "^8.57.0",
"eslint-plugin-compat": "^4.2.0",
"lesshint": "6.3.7"
"stylelint": "^16.6.1",
"stylelint-config-standard-less": "^3.0.1"
},
"overrides": {
"glob-parent": "5.1.2",
"set-value": "4.0.1",
"minimist": "~1.2.3",
"minimatch": "~3.1.2",
"ws": "^8.17.1",
"jquery": "3.6.0"
},
"scripts": {
@ -86,9 +86,9 @@
"offline": "FRESH=1 OFFLINE=1 node server.js",
"offlinedev": "DEV=1 OFFLINE=1 node server.js",
"package": "PACKAGE=1 node server.js",
"lint": "eslint . && ./node_modules/lesshint/bin/lesshint -c ./.lesshintrc ./customize.dist/src/less2/",
"lint": "eslint . && stylelint \"./customize.dist/src/less2/**/*.less\"",
"lint:js": "eslint .",
"lint:less": "./node_modules/lesshint/bin/lesshint -c ./.lesshintrc ./customize.dist/src/less2/",
"lint:less": "stylelint \"./customize.dist/src/less2/**/*.less\"",
"lint:translations": "node ./scripts/translations/lint-translations.js",
"unused-translations": "node ./scripts/translations/unused-translations.js",
"test": "node scripts/TestSelenium.js",
@ -98,5 +98,7 @@
"clear": "node scripts/clear.js",
"installtoken": "node scripts/install.js"
},
"browserslist": ["> 0.5%, last 2 versions, Firefox ESR, not dead, not op_mini all"]
"browserslist": [
"> 0.5%, last 2 versions, Firefox ESR, not dead, not op_mini all"
]
}

View file

@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later
# CryptPad
CryptPad is a collaboration suite that is end-to-end-encrypted and open-source. It is built to enable collaboration, synchronizing changes to documents in real time. Because all data are encrypted, in the eventuality of a breach, attackers have no way of seeing the stored content. Moreover, if the administators dont alter the code, they and the service also cannot infer any piece of information about the users' content.
CryptPad is a collaboration suite that is end-to-end-encrypted and open-source. It is built to enable collaboration, synchronizing changes to documents in real time. Because all data are encrypted, in the eventuality of a breach, attackers have no way of seeing the stored content. Moreover, if the administrators dont alter the code, they and the service also cannot infer any piece of information about the users' content.
![Drive screenshot](screenshot.png "preview of the CryptDrive")
@ -63,7 +63,7 @@ servers](https://cryptpad.org/instances/) that
meet our strict criteria for safety.
For end users, a [guide](https://blog.cryptpad.org/2024/03/14/Most-Secure-CryptPad-Usage/)
is provided in our blog to help understanding the security of CryptPad. This blog post
is provided in our blog to help understand the security of CryptPad. This blog post
also explains and show the best practices when using CryptPad and clarify what end-to-end
encryption entails and not.

View file

@ -2,7 +2,6 @@
//
// SPDX-License-Identifier: AGPL-3.0-or-later
/* global process */
var WebDriver = require("selenium-webdriver");
var nThen = require('nthen');

View file

@ -2,8 +2,6 @@
//
// SPDX-License-Identifier: AGPL-3.0-or-later
/* globals process */
var Fs = require("fs");
var Fse = require("fs-extra");
var Path = require("path");

View file

@ -2,7 +2,6 @@
//
// SPDX-License-Identifier: AGPL-3.0-or-later
/* globals Buffer */
var Https = require('https');
var Config = require("../lib/load-config");
var Package = require("../package.json");

View file

@ -40,5 +40,4 @@ nThen(function (w) {
console.log(token);
var url = config.httpUnsafeOrigin + '/install/';
console.log(`Please visit ${url} to create your first admin user`);
});

View file

@ -2,7 +2,6 @@
//
// SPDX-License-Identifier: AGPL-3.0-or-later
/* globals process */
const jwt = require("jsonwebtoken");
const Sessions = require("../lib/storage/sessions.js");

View file

@ -2,7 +2,6 @@
//
// SPDX-License-Identifier: AGPL-3.0-or-later
/* globals process */
var Client = require("../../lib/client");
var Nacl = require("tweetnacl/nacl-fast");
var nThen = require("nthen");

View file

@ -2,8 +2,6 @@
//
// SPDX-License-Identifier: AGPL-3.0-or-later
/* globals process */
var Client = require("../../lib/client/");
var Crypto = require("../../www/components/chainpad-crypto");
var Mailbox = Crypto.Mailbox;

View file

@ -2,8 +2,6 @@
//
// SPDX-License-Identifier: AGPL-3.0-or-later
/* globals process */
var Client = require("../../lib/client/");
var Crypto = require("../../www/components/chainpad-crypto");
var Mailbox = Crypto.Mailbox;

View file

@ -2,9 +2,6 @@
//
// SPDX-License-Identifier: AGPL-3.0-or-later
/*
globals process
*/
var Express = require('express');
var Http = require('http');
var Fs = require('fs');
@ -71,13 +68,6 @@ nThen(function (w) {
Env.Log.info("WEBSERVER_LISTENING", {
origin: url,
});
if (!Env.admins.length) {
Env.Log.info('NO_ADMIN_CONFIGURED', {
message: `Your instance is not correctly configured for production usage. Review its checkup page for more information.`,
details: new URL('/checkup/', Env.httpUnsafeOrigin).href,
});
}
} catch (err) {
Env.Log.error("INVALID_ORIGIN", {
httpUnsafeOrigin: Env.httpUnsafeOrigin,

View file

@ -9,12 +9,14 @@
@import (reference) "../../customize/src/less2/include/creation.less";
@import (reference) '../../customize/src/less2/include/framework.less';
@import (reference) '../../customize/src/less2/include/export.less';
@import (reference) '../../customize/src/less2/include/admin.less';
&.cp-app-admin {
.framework_min_main();
.sidebar-layout_main();
.limit-bar_main();
.creation_main();
.admin_main();
display: flex;
flex-flow: column;
@ -32,6 +34,16 @@
border-radius: 5px;
background-color: @cryptpad_color_brand;
}
input.cp-admin-color-picker {
vertical-align: middle;
}
.cp-palette-container {
display: inline-flex;
width: ~"calc(100% - 5rem)";
padding-left: 0.5rem;
vertical-align: middle;
}
.cp-admin-color-preview {
& > div {
margin-top: @sidebar_base-margin;

View file

@ -5,6 +5,7 @@
define([
'jquery',
'/common/toolbar.js',
'/common/pad-types.js',
'/components/nthen/index.js',
'/common/sframe-common.js',
'/common/common-interface.js',
@ -17,11 +18,11 @@ define([
'/common/hyperscript.js',
'/common/clipboard.js',
'json.sortify',
'/customize/application_config.js',
'/api/config',
'/api/instance',
'/lib/datepicker/flatpickr.js',
'/common/hyperscript.js',
'/install/onboardscreen.js',
'css!/lib/datepicker/flatpickr.min.css',
'css!/components/bootstrap/dist/css/bootstrap.min.css',
'css!/components/components-font-awesome/css/font-awesome.min.css',
@ -29,6 +30,7 @@ define([
], function(
$,
Toolbar,
PadTypes,
nThen,
SFCommon,
UI,
@ -41,11 +43,12 @@ define([
h,
Clipboard,
Sortify,
AppConfig,
ApiConfig,
Instance,
Flatpickr
Flatpickr,
Onboarding,
) {
var APP = window.APP = {};
var Nacl = window.nacl;
@ -90,6 +93,12 @@ define([
'forcemfa',
]
},
'apps': { // Msg.admin_cat_apps
icon: 'fa fa-wrench',
content: [
'apps',
]
},
'users' : { // Msg.admin_cat_users
icon : 'fa fa-address-card-o',
content : [
@ -162,6 +171,22 @@ define([
const blocks = sidebar.blocks;
// EXTENSION_POINT:ADMIN_CATEGORY
common.getExtensions('ADMIN_CATEGORY').forEach(ext => {
if (!ext || !ext.id || !ext.name || !ext.content) {
return console.error('Invalid extension point', 'ADMIN_CATEGORY', ext);
}
if (categories[ext.id]) {
return console.error('Extension point ID already used', ext);
}
console.error(ext);
categories[ext.id] = {
icon: ext.icon,
name: ext.name,
content: ext.content
};
});
const flushCache = (cb) => {
cb = cb || function () {};
sFrameChan.query('Q_ADMIN_RPC', {
@ -609,7 +634,6 @@ define([
UI.log(Messages._getKey('ui_saved', [Messages.admin_emailTitle]));
});
});
var nav = blocks.nav([button]);
var form = blocks.form([
@ -621,6 +645,35 @@ define([
cb(form);
});
sidebar.addItem('apps', function (cb) {
const appsToDisable = ApiConfig.appsToDisable || [];
const grid = Onboarding.createAppsGrid(appsToDisable);
var save = blocks.activeButton('primary', '', Messages.settings_save, function (done) {
sFrameChan.query('Q_ADMIN_RPC', {
cmd: 'ADMIN_DECREE',
data: ['DISABLE_APPS', appsToDisable]
}, function (e, response) {
if (e || response.error) {
UI.warn(Messages.error);
console.error(e, response);
done(false);
return;
}
flushCache();
done(true);
UI.log(Messages._getKey('ui_saved', [Messages.admin_appSelection]));
});
});
let form = blocks.form([
grid
], blocks.nav([save]));
cb(form);
});
sidebar.addItem('instance-info-notice', function(cb){
var key = 'instance-info-notice';
var notice = blocks.alert('info', key, [Messages.admin_infoNotice1, ' ', Messages.admin_infoNotice2]);
@ -790,7 +843,7 @@ define([
var currentContainer = blocks.block([], 'cp-admin-customize-logo');
let redraw = () => {
var current = h('img', {src: '/api/logo?'+(+new Date())});
var current = h('img', {src: '/api/logo?'+(+new Date()),alt:'Custom logo'}); // XXX
$(currentContainer).empty().append(current);
};
redraw();
@ -905,7 +958,7 @@ define([
setColor(color, done);
});
let $input = $(input).on('change', () => {
let onColorPicked = () => {
require(['/lib/less.min.js'], (Less) => {
let color = $input.val();
let lColor = Less.color(color.slice(1));
@ -925,7 +978,8 @@ define([
$preview.find('.cp-admin-color-preview-dark a').attr('style', `color: ${lightColor} !important`);
$preview.find('.cp-admin-color-preview-light a').attr('style', `color: ${color} !important`);
});
});
};
let $input = $(input).on('change', onColorPicked).addClass('cp-admin-color-picker');
UI.confirmButton($remove, {
classes: 'btn-danger',
@ -935,9 +989,18 @@ define([
setColor('', () => {});
});
var colors = UIElements.makePalette(4, (color, $color) => {
// onselect
let rgb = $color.css('background-color');
let hex = Util.rgbToHex(rgb);
$input.val(hex);
onColorPicked();
});
$(label).append(colors);
let form = blocks.form([
labelCurrent,
label
label,
], blocks.nav([btn, remove, btn.spinner]));
cb([form, labelPreview]);
@ -3226,10 +3289,6 @@ define([
$active.empty();
if (Broadcast && Broadcast.surveyURL) {
var a = blocks.link(Messages.admin_surveyActive, Broadcast.surveyURL);
$(a).click(function (e) {
e.preventDefault();
common.openUnsafeURL(Broadcast.surveyURL);
});
$active.append([a, removeButton]);
}
});
@ -3837,6 +3896,32 @@ define([
cb(opts);
});
// EXTENSION_POINT:ADMIN_ITEM
let utils = {
h, Util, Hash
};
common.getExtensions('ADMIN_ITEM').forEach(ext => {
if (!ext || !ext.id || typeof(ext.getContent) !== "function") {
return console.error('Invalid extension point', 'ADMIN_CATEGORY', ext);
}
if (sidebar.hasItem(ext.id)) {
return console.error('Extension point ID already used', ext);
}
sidebar.addItem(ext.id, cb => {
ext.getContent(common, blocks, utils, content => {
cb(content);
});
}, {
noTitle: !ext.title,
noHint: !ext.description,
title: ext.title,
hint: ext.description
});
});
sidebar.makeLeftside(categories);
};

View file

@ -240,11 +240,15 @@ define([
if (!(tab.content || tab.disabled) || !tab.title) { return; }
var content = h('div.alertify-tabs-content', tab.content);
var title = h('span.alertify-tabs-title'+ (tab.disabled ? '.disabled' : ''), h('span.tab-title-text',{id: 'cp-tab-' + tab.title.toLowerCase(), 'aria-hidden':"true"}, tab.title));
$(title).attr('tabindex', '0');
if (tab.icon) {
var icon = h('i', {class: tab.icon, 'aria-labelledby': 'cp-tab-' + tab.title.toLowerCase()});
$(title).prepend(' ').prepend(icon);
}
$(title).click(function () {
Util.onClickEnter($(title), function (event) {
event.preventDefault();
event.stopPropagation();
if (tab.disabled) { return; }
var old = tabs[active];
if (old.onHide) { old.onHide(); }
@ -300,14 +304,17 @@ define([
var $root = $t.parent();
var $input = $root.find('.token-input');
$input.attr('tabindex', 0);
var $button = $(h('button.btn.btn-primary', [
h('i.fa.fa-plus'),
h('span', Messages.tag_add)
]));
$button.click(function () {
Util.onClickEnter($button, function (e) {
$t.tokenfield('createToken', $input.val());
e.stopPropagation();
});
var $container = $(h('span.cp-tokenfield-container'));
@ -325,27 +332,47 @@ define([
if (!$tokens.length) {
$container.prepend(h('span.tokenfield-empty', Messages.kanban_noTags));
}
$tokens.find('.close').attr('tabindex', 0).on('keydown', e => {
e.stopPropagation();
});
$tokens.find('.token-label').attr('tabindex', 0).on('keydown', function (e) {
if (e.which === 13 || e.which === 32) {
$(this).dblclick();
}
e.stopPropagation();
});
$form.append($input);
$form.append($button);
if (isEdit) { $button.find('span').text(Messages.tag_edit); }
else { $button.find('span').text(Messages.add); }
$container.append($form);
$input.focus();
isEdit = false;
called = false;
});
};
resetUI();
const focusInput = () => {
let active = document.activeElement;
if ($.contains($container[0], active)) {
setTimeout(() => {
$input.focus();
});
}
};
$t.on('tokenfield:removedtoken', function () {
resetUI();
focusInput();
});
$t.on('tokenfield:editedtoken', function () {
resetUI();
focusInput();
});
$t.on('tokenfield:createdtoken', function () {
$input.val('');
resetUI();
focusInput();
});
$t.on('tokenfield:edittoken', function () {
isEdit = true;
@ -486,7 +513,7 @@ define([
var navs = [];
buttons.forEach(function (b) {
if (!b.name || !b.onClick) { return; }
var button = h('button', { tabindex: '1', 'class': b.className || '' }, [
var button = h('button', { 'class': b.className || '' }, [
b.iconClass ? h('i' + b.iconClass) : undefined,
b.name
]);
@ -509,7 +536,8 @@ define([
divClasses: 'left'
}, todo);
} else {
$(button).click(function () {
Util.onClickEnter($(button), function (e) {
e.stopPropagation();
todo();
});
}
@ -548,6 +576,40 @@ define([
if (opt.forefront) { $(frame).addClass('forefront'); }
return frame;
};
let addTabListener = frame => {
// find focusable elements
let modalElements = $(frame).find('a, button, input, [tabindex]:not([tabindex="-1"]), textarea').filter(':visible').filter(':not(:disabled)');
if (modalElements.length === 0) {
// there are no focusable elements -> nothing to do for us here
return;
}
// intialize with focus on first element
modalElements[0].focus();
$(frame).on('keydown', function (e) {
modalElements = $(frame).find('a, button, input, [tabindex]:not([tabindex="-1"]), textarea').filter(':visible').filter(':not(:disabled)'); // for modals with dynamic content
if (e.which === 9) { // Tab
if (e.shiftKey) {
// On the first element, shift+tab goes to last
if (document.activeElement === modalElements[0]) {
e.preventDefault();
modalElements[modalElements.length - 1].focus();
}
} else {
// On the last element, tab goes to first
if (document.activeElement === modalElements[modalElements.length - 1]) {
e.preventDefault();
modalElements[0].focus();
}
}
}
});
};
UI.openCustomModal = function (content, opt) {
var frame = dialog.frame([
content
@ -564,6 +626,9 @@ define([
setTimeout(function () {
Notifier.notify();
});
addTabListener(frame);
return frame;
};
@ -742,13 +807,28 @@ define([
var $ok = $(ok).click(function (ev) { close(true, ev); });
var $cancel = $(cancel).click(function (ev) { close(false, ev); });
document.body.appendChild(frame);
addTabListener(frame);
frame.addEventListener('keydown', function(e) {
if (e.keyCode === 13) {
if (document.activeElement === $ok[0]) {
$ok.click();
} else if (document.activeElement === $cancel[0]) {
$cancel.click();
}
} else if (e.keyCode === 27) {
$cancel.click();
}
});
listener = listenForKeys(function () {
$ok.click();
}, function () {
$cancel.click();
}, frame);
document.body.appendChild(frame);
setTimeout(function () {
Notifier.notify();
$(frame).find('.ok').focus();
@ -815,15 +895,19 @@ define([
};
var newCls2 = config.new ? 'new' : '';
$(originalBtn).addClass('cp-button-confirm-placeholder').addClass(newCls2).click(function (e) {
e.stopPropagation();
// If we have a validation function, continue only if it's true
if (config.validate && !config.validate()) { return; }
i = 1;
to = setTimeout(todo, INTERVAL);
$(originalBtn).hide().after(content);
$(originalBtn).addClass('cp-button-confirm-placeholder').addClass(newCls2).on('click keydown', function (e) {
if (e.type === 'click' || (e.type === 'keydown' && e.key === 'Enter')) {
e.stopPropagation();
// If we have a validation function, continue only if it's true
if (config.validate && !config.validate()) { return; }
i = 1;
to = setTimeout(todo, INTERVAL);
$(originalBtn).hide().after(content);
$(button).focus();
}
});
return {
reset: function () {
done(false);
@ -877,12 +961,14 @@ define([
opts = opts || {};
var attributes = merge({
type: 'password',
tabindex: '1',
tabindex: '0',
autocomplete: 'one-time-code', // https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete#values
}, opts);
var input = h('input.cp-password-input', attributes);
var eye = h('span.fa.fa-eye.cp-password-reveal');
var eye = h('span.fa.fa-eye.cp-password-reveal', {
tabindex: 0
});
var $eye = $(eye);
var $input = $(input);
@ -899,7 +985,8 @@ define([
$input.focus();
});
} else {
$eye.click(function () {
Util.onClickEnter($eye, function (e) {
e.stopPropagation();
if ($eye.hasClass('fa-eye')) {
$input.prop('type', 'text');
$input.focus();
@ -925,7 +1012,8 @@ define([
title: text,
href: href,
target: "_blank",
'data-tippy-placement': "right"
'data-tippy-placement': "right",
'aria-label': Messages.help_genericMore //TBC XXX
});
return q;
};
@ -1064,6 +1152,21 @@ define([
}
};
UI.getNewIcon = function (type) {
var icon = h('i.fa.fa-file-text-o');
if (AppConfig.applicationsIcon && AppConfig.applicationsIcon[type]) {
icon = AppConfig.applicationsIcon[type];
var font = icon.indexOf('cptools') === 0 ? 'cptools' : 'fa';
if (type === 'fileupload') { type = 'file'; }
if (type === 'folderupload') { type = 'file'; }
if (type === 'link') { type = 'drive'; }
var appClass = ' cp-icon cp-icon-color-'+type;
icon = h('i', {'class': font + ' ' + icon + appClass});
}
return icon;
};
var $defaultIcon = $('<span>', {"class": "fa fa-file-text-o"});
UI.getIcon = function (type) {
var $icon = $defaultIcon.clone();
@ -1205,18 +1308,18 @@ define([
if (labelOpts.class) { labelOpts.class += ' cp-checkmark'; }
// Mark properties
var markOpts = { tabindex: 0 };
var markOpts = { tabindex: 0, role: 'checkbox', 'aria-checked': checked, 'aria-labelledby': inputOpts.id + '-label' };
$.extend(markOpts, opts.mark || {});
var input = h('input', inputOpts);
var $input = $(input);
var mark = h('span.cp-checkmark-mark', markOpts);
var $mark = $(mark);
var label = h('span.cp-checkmark-label', labelTxt);
var label = h('span.cp-checkmark-label', {id: inputOpts.id + '-label'}, labelTxt);
$mark.keydown(function (e) {
if ($input.is(':disabled')) { return; }
if (e.which === 32) {
if (e.which === 32 || e.which === 13){
e.stopPropagation();
e.preventDefault();
$input.prop('checked', !$input.is(':checked'));
@ -1228,8 +1331,10 @@ define([
if (!opts.labelAlt) { return; }
if ($input.is(':checked') !== checked) {
$(label).text(opts.labelAlt);
$mark.attr('aria-checked', 'true');
} else {
$(label).text(labelTxt);
$mark.attr('aria-checked', 'false');
}
});
@ -1267,7 +1372,7 @@ define([
$(mark).keydown(function (e) {
if ($input.is(':disabled')) { return; }
if (e.which === 32) {
if (e.which === 13 || e.which === 32) {
e.stopPropagation();
e.preventDefault();
if ($input.is(':checked')) { return; }

View file

@ -173,8 +173,12 @@ define([
var removeBtn, el;
if (config.remove) {
removeBtn = h('span.fa.fa-times');
$(removeBtn).click(function () {
config.remove(el);
$(removeBtn).attr('tabindex', '0');
$(removeBtn).on('click keydown', function(event) {
if (event.type === 'click' || (event.type === 'keydown' && event.key === 'Enter')) {
event.preventDefault();
config.remove(el);
}
});
}
@ -184,6 +188,7 @@ define([
'data-curve': data.curvePublic || '',
'data-name': name.toLowerCase(),
'data-order': i,
'tabindex': config.noSelect ? '-1' : '0',
style: 'order:'+i+';'
},[
avatar,
@ -231,6 +236,13 @@ define([
}
onSelect();
});
$div.on('keydown', '.cp-usergrid-user', function (e) {
if (e.which === 13) {
e.preventDefault();
e.stopPropagation();
$(this).trigger('click');
}
});
}
return {
@ -2645,7 +2657,7 @@ define([
var urlArgs = (Config.requireConf && Config.requireConf.urlArgs) || '';
var logo = h('img', { src: '/customize/CryptPad_logo.svg?' + urlArgs });
var fill1 = h('div.cp-creation-fill.cp-creation-logo', logo);
var fill1 = h('div.cp-creation-fill.cp-creation-logo',{ role: 'presentation' }, logo);
var fill2 = h('div.cp-creation-fill');
var $creation = $('<div>', { id: 'cp-creation', tabindex:1 });
$creationContainer.append([fill1, $creation, fill2]);
@ -4285,5 +4297,76 @@ define([
return UI.errorLoadingScreen(msg, false, false);
};
UIElements.makePalette = (maxColors, onSelect) => {
let palette = [''];
for (var i=1; i<=maxColors; i++) { palette.push('color'+i); }
let offline = false;
let selectedColor = '';
let container = h('div.cp-palette-container');
let $container = $(container);
var all = [];
palette.forEach(function (color, i) {
var $color = $(h('button.cp-palette-color.fa'));
all.push($color);
$color.addClass('cp-palette-'+(color || 'nocolor'));
$color.keydown(function (e) {
if (e.which === 13) {
e.stopPropagation();
e.preventDefault();
$color.click();
}
});
$color.click(function () {
if (offline) { return; }
if (color === selectedColor) { return; }
selectedColor = color;
$container.find('.cp-palette-color').removeClass('fa-check');
$color.addClass('fa-check');
onSelect(color, $color);
}).appendTo($container);
$color.keydown(e => {
if (e.which === 37) {
e.preventDefault();
if (i === 0) {
all[all.length - 1].focus();
} else {
all[i - 1].focus();
}
}
if (e.which === 39) {
e.preventDefault();
if (i === (all.length - 1)) {
all[0].focus();
} else {
all[i + 1].focus();
}
}
if (e.which === 9) {
if (e.shiftKey) {
all[0].focus();
return;
}
all[all.length - 1].focus();
}
});
});
container.disable = state => {
offline = !!state;
};
container.getValue = () => {
return selectedColor;
};
container.setValue = color => {
$container.find('.cp-palette-color').removeClass('fa-check');
let $color = $container.find('.cp-palette-'+(color || 'nocolor'));
$color.addClass('fa-check');
selectedColor = color;
};
return container;
};
return UIElements;
});

View file

@ -606,6 +606,9 @@
parseInt(h.slice(4,6), 16),
];
};
Util.rgbToHex = function (rgb) {
return `#${rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/).slice(1).map(n => parseInt(n, 10).toString(16).padStart(2, '0')).join('')}`;
};
Util.isSmallScreen = function () {
return window.innerHeight < 800 || window.innerWidth < 800;

View file

@ -2822,6 +2822,15 @@ define([
initFeedback(data.feedback);
}
if (data.edPublic) {
if (Array.isArray(Config.adminKeys) &&
Config.adminKeys.includes(data.edPublic)) {
// Doesn't provides extra-rights but may show
// additional warnings in the UI
localStorage.CP_admin = "1";
}
}
if (data.loggedIn) {
window.CP_logged_in = true;
}

View file

@ -1197,11 +1197,12 @@ define([
});
};
// `app`: true (force open wiht the app), false (force open in preview),
// `app`: true (force open with the app), false (force open in preview),
// falsy (open in preview if default is not using the app)
var defaultInApp = ['application/pdf'];
var openFile = function (el, isRo, app) {
var data = manager.getFileData(el);
// In anonymous drives, `el` already contains file data
var data = el.channel ? el : manager.getFileData(el);
if (data.static) {
if (data.href) {
@ -2246,6 +2247,7 @@ define([
$element.prepend(img);
$(img).addClass('cp-app-drive-element-grid cp-app-drive-element-thumbnail');
$(img).attr("draggable", false);
$(img).attr("role", "presentation");
addTitleIcon(element, $name);
} else {
common.displayThumbnail(href || data.roHref, data.channel, data.password, $element, function ($thumb) {

63
www/common/extensions.js Normal file
View file

@ -0,0 +1,63 @@
// SPDX-FileCopyrightText: 2024 XWiki CryptPad Team <contact@cryptpad.org> and contributors
//
// SPDX-License-Identifier: AGPL-3.0-or-later
define([
'optional!/extensions.js'
], (Extensions) => {
const ext = {};
ext.getExtensions = id => {
let e = ext[id];
if (!Array.isArray(e)) { e = []; }
return e;
};
if (!Array.isArray(Extensions) || !Extensions.length) { return ext; }
let all = Extensions.slice();
while(all.length) {
let current = all.splice(0, 3);
let f = current[0];
if (typeof(f) !== "function") {
continue;
}
let defaultLang = current[1];
let lang = current[2];
if (!Object.keys(lang).length && Object.keys(defaultLang).length) {
// If our language doesn't exists, use default
lang = defaultLang;
} else if (Object.keys(defaultLang).length) {
// Otherwise fill our language with missing keys
Object.keys(defaultLang).forEach(key => {
if (typeof(lang[key]) !== "undefined") { return; }
lang[key] = defaultLang[key];
});
}
lang._getKey = function (key, argArray) {
if (!lang[key]) { return '?'; }
var text = lang[key];
if (typeof(text) === 'string') {
return text.replace(/\{(\d+)\}/g, function (str, p1) {
if (typeof(argArray[p1]) === 'string' || typeof(argArray[p1]) === "number") {
return argArray[p1];
}
return '';
});
} else {
return text;
}
};
let currentExt = f(lang) || {};
Object.keys(currentExt).forEach(key => {
ext[key] = ext[key] || [];
Array.prototype.push.apply(ext[key], currentExt[key]); // concat in place
});
}
return ext;
});

View file

@ -367,6 +367,13 @@ define([
UI.log(Messages.saved);
});
});
$(addBtn).on('keydown', function () {
if (event.keyCode === 13) {
event.preventDefault();
event.stopPropagation();
$(addBtn).click();
}
});
var called = false;
redrawAll = function (reload) {
@ -459,6 +466,9 @@ define([
var setLock = function (locked) {
$(link).find('.cp-overlay').toggle(locked);
$(link).find('.cp-usergrid-user').attr('tabindex', locked ? -1 : 0);
$(link).find('.cp-usergrid-filter input').prop('disabled', locked);
$(link).find('.cp-access-add').prop('disabled', locked);
};
// Remove owner column
@ -714,6 +724,13 @@ define([
UI.log(Messages.saved);
});
});
$(addBtn).on('keydown', function () {
if (event.keyCode === 13) {
event.preventDefault();
event.stopPropagation();
$(addBtn).click();
}
});
var called = false;
redrawAll = function (reload) {
@ -1025,6 +1042,13 @@ define([
});
});
});
$(passwordOk).on('keydown', function (e) {
if (e.keyCode === 13) {
e.preventDefault();
e.stopPropagation();
$(passwordOk).click();
}
});
$d.append(changePass);
}
if (owned) {

View file

@ -385,13 +385,13 @@ define([
h('label', Messages.sharedFolders_share),
h('br'),
] : [
UI.createCheckbox('cp-share-embed', Messages.share_linkEmbed, false, { mark: {tabindex:1} }),
UI.createCheckbox('cp-share-embed', Messages.share_linkEmbed, false, { mark: {tabindex:0} }),
];
if (opts.static) { linkContent = []; }
linkContent.push(h('div.cp-spacer'));
linkContent.push(UI.dialog.selectableArea('', { id: 'cp-share-link-preview', tabindex: 1, rows:3}));
linkContent.push(UI.dialog.selectableArea('', { id: 'cp-share-link-preview', tabindex: 0, rows:3}));
// Show alert if the pad is password protected
if (opts.hasPassword) {
@ -553,7 +553,7 @@ define([
var embedContent = [
h('p', Messages.viewEmbedTag),
UI.dialog.selectableArea(opts.getEmbedValue(), { id: 'cp-embed-link-preview', tabindex: 1, rows: 3})
UI.dialog.selectableArea(opts.getEmbedValue(), { id: 'cp-embed-link-preview', tabindex: 0, rows: 3})
];
// Show alert if the pad is password protected
@ -611,24 +611,24 @@ define([
labelEdit = Messages.share_formEdit;
labelView = Messages.share_formView;
auditor = UI.createRadio('accessRights', 'cp-share-form', Messages.share_formAuditor, false, {
mark: {tabindex:1},
mark: {tabindex:0},
});
}
var burnAfterReading = (hashes.viewHash && canBAR) ?
UI.createRadio('accessRights', 'cp-share-bar', Messages.burnAfterReading_linkBurnAfterReading, false, {
mark: {tabindex:1},
mark: {tabindex:0},
label: {style: "display: none;"}
}) : undefined;
var rights = h('div.msg.cp-inline-radio-group', [
h('label',{ for: 'cp-share-editable-true' }, Messages.share_linkAccess),
h('div.radio-group',[
UI.createRadio('accessRights', 'cp-share-editable-false',
labelView, true, { mark: {tabindex:1} }),
labelView, true, { mark: {tabindex:0} }),
canPresent ? UI.createRadio('accessRights', 'cp-share-present',
Messages.share_linkPresent, false, { mark: {tabindex:1} }) : undefined,
UI.createRadio('accessRights', 'cp-share-editable-true',
labelEdit, false, { mark: {tabindex:1} }),
labelEdit, false, { mark: {tabindex:0} }),
auditor]),
burnAfterReading,
]);
@ -921,7 +921,7 @@ define([
var cb = Util.once(Util.mkAsync(_cb));
var linkContent = [
UI.dialog.selectableArea(opts.getLinkValue(), {
id: 'cp-share-link-preview', tabindex: 1, rows:2
id: 'cp-share-link-preview', tabindex: 0, rows:2
})
];

View file

@ -4,6 +4,7 @@
define([
'jquery',
'/api/config',
'/components/nthen/index.js',
'/common/common-interface.js',
'/common/common-ui-elements.js',
@ -13,6 +14,7 @@ define([
'/common/hyperscript.js',
], function(
$,
ApiConfig,
nThen,
UI,
UIElements,
@ -22,17 +24,26 @@ define([
h
) {
const Sidebar = {};
const keyToCamlCase = (key) => {
return key.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
};
Sidebar.create = function (common, app, $container) {
const $leftside = $(h('div#cp-sidebarlayout-leftside')).appendTo($container);
const $rightside = $(h('div#cp-sidebarlayout-rightside')).appendTo($container);
const sidebar = {
$leftside,
$rightside
};
const items = {};
Sidebar.blocks = function (app, common) {
let blocks = {};
// sframe-common shim
if (!common) {
common = {
openURL: url => {
window.open(url);
},
openUnsafeURL: url => {
window.open(ApiConfig.httpSafeOrigin + '/bounce/#' + encodeURIComponent(url));
}
};
}
let blocks = sidebar.blocks = {};
blocks.labelledInput = (label, input, inputBlock) => {
let uid = Util.uid();
let id = `cp-${app}-item-${uid}`;
@ -109,7 +120,7 @@ define([
element
]);
};
blocks.pre = (value) => {
blocks.pre = (value) => {
return h('pre', value);
};
@ -220,9 +231,7 @@ define([
return button;
};
const keyToCamlCase = (key) => {
return key.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
};
blocks.activeCheckbox = (data) => {
const state = data.getState();
const key = data.key;
@ -246,34 +255,52 @@ define([
return box;
};
return blocks;
};
Sidebar.create = function (common, app, $container) {
const $leftside = $(h('div#cp-sidebarlayout-leftside')).appendTo($container);
const $rightside = $(h('div#cp-sidebarlayout-rightside')).appendTo($container);
const sidebar = {
$leftside,
$rightside
};
const items = {};
sidebar.blocks = Sidebar.blocks(app, common);
sidebar.addItem = (key, get, options) => {
const safeKey = keyToCamlCase(key);
const div = h(`div.cp-sidebarlayout-element`, {
'data-item': key,
style: 'display:none;'
});
items[key] = div;
$rightside.append(div);
get((content) => {
if (content === false) { return; }
if (content === false) {
delete items[key];
return void $(div).remove();
}
options = options || {};
const title = options.noTitle ? undefined : h('label.cp-item-label', {
id: `cp-${app}-${key}`
}, Messages[`${app}_${safeKey}Title`] || key);
}, options.title || Messages[`${app}_${safeKey}Title`] || key);
const hint = options.noHint ? undefined : h('span.cp-sidebarlayout-description',
Messages[`${app}_${safeKey}Hint`] || 'Coming soon...');
options.hint || Messages[`${app}_${safeKey}Hint`] || 'Coming soon...');
if (hint && options.htmlHint) {
hint.innerHTML = Messages[`${app}_${safeKey}Hint`];
}
const div = h(`div.cp-sidebarlayout-element`, {
'data-item': key,
style: 'display:none;'
}, [
title,
hint,
content
]);
items[key] = div;
$rightside.append(div);
$(div).append(title).append(hint).append(content);
});
};
sidebar.hasItem = key => {
return !key || !!items[key];
};
sidebar.addCheckboxItem = (data) => {
const key = data.key;
let blocks = sidebar.blocks;
let box = blocks.activeCheckbox(data);
sidebar.addItem(key, function (cb) {
cb(box);
@ -325,7 +352,7 @@ define([
'data-category': key
}, [
icon,
Messages[`${app}_cat_${key}`] || key,
category.name || Messages[`${app}_cat_${key}`] || key,
]);
var $item = $(item).appendTo(container);
Util.onClickEnter($item, function () {

View file

@ -107,9 +107,11 @@ define([
var myOOId;
var sessionId = Hash.createChannelId();
var cpNfInner;
let integrationChannel;
var evOnPatch = Util.mkEvent();
var evOnSync = Util.mkEvent();
var evIntegrationSave = Util.mkEvent();
// This structure is used for caching media data and blob urls for each media cryptpad url
var mediasData = {};
@ -179,15 +181,11 @@ define([
});
};
var getUserIndex = function () {
var i = 1;
var ids = content.ids || {};
Object.keys(ids).forEach(function (k) {
if (ids[k] && ids[k].index && ids[k].index >= i) {
i = ids[k].index + 1;
}
});
return i;
const getNewUserIndex = function () {
const ids = content.ids || {};
const indexes = Object.values(ids).map((user) => user.index);
const maxIndex = Math.max(...indexes);
return maxIndex === -Infinity ? 1 : maxIndex+1;
};
var setMyId = function () {
@ -198,7 +196,7 @@ define([
myOOId = Util.createRandomInteger();
// f: function used in .some(f) but defined outside of the while
var f = function (id) {
return ids[id] === myOOId;
return ids[id].ooid === myOOId;
};
while (Object.keys(ids).some(f)) {
myOOId = Util.createRandomInteger();
@ -207,7 +205,7 @@ define([
var myId = getId();
ids[myId] = {
ooid: myOOId,
index: getUserIndex(),
index: getNewUserIndex(),
netflux: metadataMgr.getNetfluxId()
};
oldIds = JSON.parse(JSON.stringify(ids));
@ -317,7 +315,10 @@ define([
isCp: cp
}
}, function (err, h) {
if (!err) { evOnSync.fire(); }
if (!err) {
evOnSync.fire();
evIntegrationSave.fire();
}
cb(err, h);
});
},
@ -912,6 +913,15 @@ define([
});
};
const findUserByOOId = function(ooId) {
return Object.values(content.ids)
.find((user) => user.ooid === ooId);
};
const getMyOOIndex = function() {
return findUserByOOId(myOOId).index;
};
var getParticipants = function () {
var users = metadataMgr.getMetadata().users;
var i = 1;
@ -943,19 +953,19 @@ define([
isCloseCoAuthoring:false,
view: false
});
i++;
if (!myUniqueOOId) { myUniqueOOId = String(myOOId) + i; }
const myOOIndex = getMyOOIndex();
if (!myUniqueOOId) { myUniqueOOId = String(myOOId) + myOOIndex; }
p.push({
id: myUniqueOOId,
id: String(myOOId),
idOriginal: String(myOOId),
username: metadataMgr.getUserData().name || Messages.anonymous,
indexUser: i,
indexUser: myOOIndex,
connectionId: metadataMgr.getNetfluxId() || Hash.createChannelId(),
isCloseCoAuthoring:false,
view: false
});
return {
index: i,
index: myOOIndex,
list: p.filter(Boolean)
};
};
@ -1418,6 +1428,9 @@ define([
debug(obj, 'toOO');
chan.event('CMD', obj);
if (obj && obj.type === "saveChanges") {
evIntegrationSave.fire();
}
};
chan.on('CMD', function (obj) {
@ -1592,13 +1605,15 @@ define([
var x2tConvertData = function (data, fileName, format, cb) {
var sframeChan = common.getSframeChannel();
var e = getEditor();
var fonts = e && e.FontLoader.fontInfos;
var files = e && e.FontLoader.fontFiles.map(function (f) {
var editor = getEditor();
var fonts = editor && editor.FontLoader.fontInfos;
var files = editor && editor.FontLoader.fontFiles.map(function (f) {
return { 'Id': f.Id, };
});
var type = common.getMetadataMgr().getPrivateData().ooType;
var images = (e && window.frames[0].AscCommon.g_oDocumentUrls.urls) || {};
const images = editor
? structuredClone(window.frames[0].AscCommon.g_oDocumentUrls.getUrls())
: {};
// Fix race condition which could drop images sometimes
// ==> make sure each image has a 'media/image_name.ext' entry as well
@ -1609,7 +1624,7 @@ define([
});
// Add theme images
var theme = e && window.frames[0].AscCommon.g_image_loader.map_image_index;
var theme = editor && window.frames[0].AscCommon.g_image_loader.map_image_index;
if (theme) {
Object.keys(theme).forEach(function (url) {
if (!/^(\/|blob:|data:)/.test(url)) {
@ -1623,7 +1638,7 @@ define([
type: type,
fileName: fileName,
outputFormat: format,
images: (e && window.frames[0].AscCommon.g_oDocumentUrls.urls) || {},
images: (editor && window.frames[0].AscCommon.g_oDocumentUrls.urls) || {},
fonts: fonts,
fonts_files: files,
mediasSources: getMediasSources(),
@ -1837,6 +1852,11 @@ define([
}
delete APP.oldCursor;
}
if (integrationChannel) {
APP.onDocumentUnlock = () => {
integrationChannel.event('EV_INTEGRATION_READY');
};
}
}
delete APP.startNew;
@ -2051,6 +2071,15 @@ Uncaught TypeError: Cannot read property 'calculatedType' of null
if (blobUrl) {
delete downloadImages[name];
debug("CryptPad Image already loaded " + blobUrl);
// Fix: https://github.com/cryptpad/cryptpad/issues/1500
// Maybe OO was reloaded, but the CryptPad cache is still intact?
// -> Add the image to OnlyOffice again.
const documentUrls = window.frames[0].AscCommon.g_oDocumentUrls;
if (!(data.name in documentUrls.getUrls())) {
documentUrls.addImageUrl(data.name, blobUrl);
}
return void callback(blobUrl);
}
@ -2564,6 +2593,22 @@ Uncaught TypeError: Cannot read property 'calculatedType' of null
});
};
sframeChan.on('EV_INTEGRATION_DOWNLOADAS', function (format) {
console.error('DOWNLOAD AS RECEIVED');
var data = getContent();
x2tConvertData(data, "document.bin", format, function (xlsData) {
UI.removeModals();
if (xlsData) {
var blob = new Blob([xlsData], {type: "application/bin;charset=utf-8"});
if (integrationChannel) {
integrationChannel.event('EV_INTEGRATION_ON_DOWNLOADAS',
blob, { raw: true });
}
return;
}
UI.warn(Messages.error);
});
});
sframeChan.on('EV_OOIFRAME_REFRESH', function (data) {
// We want to get the "bin" content of a sheet from its json in order to download
// something useful from a non-onlyoffice app (download from drive or settings).
@ -2668,7 +2713,6 @@ Uncaught TypeError: Cannot read property 'calculatedType' of null
};
var onCheckpoint = function (cp) {
// We want to load a checkpoint:
console.log('XXX onCheckpoint', JSON.stringify(cp));
loadCp(cp);
};
var setHistoryMode = function (bool) {
@ -3117,6 +3161,73 @@ Uncaught TypeError: Cannot read property 'calculatedType' of null
UI.removeLoadingScreen();
};
let convertImportBlob = (blob, title) => {
new Response(blob).arrayBuffer().then(function (buffer) {
var u8Xlsx = new Uint8Array(buffer);
x2tImportData(u8Xlsx, title, 'bin', function (bin) {
if (!bin) {
return void UI.errorLoadingScreen(Messages.error);
}
var blob = new Blob([bin], {type: 'text/plain'});
var file = getFileType();
resetData(blob, file);
//saveToServer(blob, title);
Title.updateTitle(title);
UI.removeLoadingScreen();
});
});
};
if (privateData.integration) {
let cfg = privateData.integrationConfig || {};
common.openIntegrationChannel(APP.onLocal);
integrationChannel = common.getSframeChannel();
var integrationSave = function (cb) {
var ext = cfg.fileType;
var upload = Util.once(function (_blob) {
integrationChannel.query('Q_INTEGRATION_SAVE', {
blob: _blob
}, cb, {
raw: true
});
});
var data = getContent();
x2tConvertData(data, "document.bin", ext, function (xlsData) {
UI.removeModals();
if (xlsData) {
var blob = new Blob([xlsData], {type: "application/bin;charset=utf-8"});
upload(blob);
return;
}
UI.warn(Messages.error);
});
};
const integrationHasUnsavedChanges = function(unsavedChanges, cb) {
integrationChannel.query('Q_INTEGRATION_HAS_UNSAVED_CHANGES', unsavedChanges, cb);
};
var inte = common.createIntegration(integrationSave,
integrationHasUnsavedChanges);
if (inte) {
evIntegrationSave.reg(function () {
inte.changed();
});
}
integrationChannel.on('Q_INTEGRATION_NEEDSAVE', function (data, cb) {
integrationSave(function (obj) {
if (obj && obj.error) { console.error(obj.error); }
cb();
});
});
if (privateData.initialState) {
var blob = privateData.initialState;
let title = `document.${cfg.fileType}`;
console.error(blob, title);
return convertImportBlob(blob, title);
}
}
if (privateData.isNewFile && privateData.fromFileData) {
try {
(function () {

View file

@ -11,12 +11,15 @@ define([
'/common/sframe-common-outer.js'
], function (nThen, ApiConfig, DomReady, Hash, SFCommonO) {
var isIntegration = Boolean(window.CP_integration_outer);
var integration = window.CP_integration_outer || {};
// Loaded in load #2
var hash, href, version;
nThen(function (waitFor) {
DomReady.onReady(waitFor());
}).nThen(function (waitFor) {
var obj = SFCommonO.initIframe(waitFor, true);
var obj = SFCommonO.initIframe(waitFor, true, integration.pathname);
href = obj.href;
hash = obj.hash;
var parsed = Hash.parsePadUrl(href);
@ -24,9 +27,14 @@ define([
var opts = parsed.getOptions();
version = opts.versionHash;
}
if (isIntegration) {
href = integration.href;
hash = integration.hash;
}
}).nThen(function (/*waitFor*/) {
var addData = function (obj) {
obj.ooType = window.location.pathname.replace(/^\//, '').replace(/\/$/, '');
let path = (integration && integration.pathname) || window.location.pathname;
obj.ooType = path.replace(/^\//, '').replace(/\/$/, '');
obj.ooVersionHash = version;
obj.ooForceVersion = localStorage.CryptPad_ooVersion || "";
};
@ -154,18 +162,21 @@ define([
Utils.initUnsafeIframe(obj, cb);
});
};
SFCommonO.start({
hash: hash,
href: href,
type: 'oo',
useCreationScreen: true,
addData: addData,
addRpc: addRpc,
getPropChannels: getPropChannels,
messaging: true
messaging: true,
useCreationScreen: !isIntegration,
noDrive: true,
integration: isIntegration,
integrationUtils: integration.utils,
integrationConfig: integration.config || {},
initialState: integration.initialState || undefined
});
});
});

File diff suppressed because it is too large Load diff

Binary file not shown.

View file

@ -3014,6 +3014,8 @@ define([
// Make sure we have a valid user object before emitting cacheready
if (rt.proxy && !rt.proxy.drive) { return; }
returned.edPublic = rt.proxy.edPublic;
onCacheReady(clientId, function () {
if (typeof(cb) === "function") { cb(returned); }
onCacheReadyEvt.fire();
@ -3047,6 +3049,8 @@ define([
drive[Constants.oldStorageKey] = [];
}
*/
returned.edPublic = rt.proxy.edPublic;
// Drive already exist: return the existing drive, don't load data from legacy store
if (store.manager) {
// If a cache is loading, make sure it is complete before calling onReady
@ -3156,6 +3160,7 @@ define([
loadUniversal(Cursor, 'cursor', function () {});
loadUniversal(Integration, 'integration', function () {});
loadUniversal(Messenger, 'messenger', function () {});
loadOnlyOffice();
store.messenger = store.modules['messenger'];
// And now we're ready

View file

@ -6,8 +6,8 @@
importScripts('/components/requirejs/require.js');
window = self;
localStorage = {
window = self; // eslint-disable-line no-global-assign
localStorage = { // eslint-disable-line no-global-assign
setItem: function (k, v) { localStorage[k] = v; },
getItem: function (k) { return localStorage[k]; }
};

View file

@ -6,8 +6,8 @@
importScripts('/components/requirejs/require.js');
window = self;
localStorage = {
window = self; // eslint-disable-line no-global-assign
localStorage = { // eslint-disable-line no-global-assign
setItem: function (k, v) { localStorage[k] = v; },
getItem: function (k) { return localStorage[k]; }
};

View file

@ -6,8 +6,8 @@
importScripts('/components/requirejs/require.js');
window = self;
localStorage = {
window = self; // eslint-disable-line no-global-assign
localStorage = { // eslint-disable-line no-global-assign
setItem: function (k, v) { localStorage[k] = v; },
getItem: function (k) { return localStorage[k]; }
};

View file

@ -12,7 +12,7 @@ define([
var CURRENT_VERSION = X2T.CURRENT_VERSION = CurrentVersion.currentVersion;
var debug = function (str) {
if (localStorage.CryptPad_dev !== "1") { return; }
//if (localStorage.CryptPad_dev !== "1") { return; }
console.debug(str);
};
@ -65,7 +65,7 @@ define([
};
var getX2T = function (cb) {
// Perform the x2t conversion
require(['/common/onlyoffice/x2t/x2t.js'], function() { // FIXME why does this fail without an access-control-allow-origin header?
require(['/common/onlyoffice/dist/x2t/x2t.js'], function() { // FIXME why does this fail without an access-control-allow-origin header?
var x2t = window.Module;
if (x2tInitialized) {
debug("x2t runtime already initialized");

View file

@ -12,12 +12,22 @@ define([
OOCurrentVersion.currentVersion,
);
let availableTypes = AppConfig.availablePadTypes.filter(
(t) => ooEnabled || !OO_APPS.includes(t),
let availablePadTypes = AppConfig.availablePadTypes.filter(
(t) => ooEnabled || !OO_APPS.includes(t)
);
let availableTypes;
if (ApiConfig.appsToDisable) {
availableTypes = availablePadTypes.filter(value => !ApiConfig.appsToDisable.includes(value));
} else {
availableTypes = availablePadTypes;
}
var appsToSelect = availablePadTypes.filter(value => !['drive', 'teams', 'file', 'contacts', 'convert'].includes(value));
return {
availableTypes,
appsToSelect,
isAvailable: function (type) {
return availableTypes.includes(type);

View file

@ -648,8 +648,8 @@ define([
const integrationHasUnsavedChanges = function(unsavedChanges, cb) {
integrationChannel.query('Q_INTEGRATION_HAS_UNSAVED_CHANGES', unsavedChanges, cb);
};
var inte = common.createIntegration(onLocal, cpNfInner.chainpad,
integrationSave, integrationHasUnsavedChanges);
var inte = common.createIntegration(integrationSave,
integrationHasUnsavedChanges);
if (inte) {
integration = true;
evIntegrationSave.reg(function () {

View file

@ -176,6 +176,10 @@ define([
else { editor.execCommand("insertTab"); }
}
},
//remove focus from editor
"Esc": function () {
editor.display.input.blur();
},
"Shift-Tab": function () {
editor.execCommand("indentLess");
},

View file

@ -9,8 +9,6 @@ define([
module.create = function (
Common,
onLocal,
chainpad,
saveHandler,
unsavedChangesHandler) {

View file

@ -78,6 +78,7 @@ define([
requireConfig.urlArgs + '#' + encodeURIComponent(JSON.stringify(req)));
$i.attr('allowfullscreen', 'true');
$i.attr('allow', 'clipboard-write');
$i.attr('title', 'iframe');
$('iframe-placeholder').after($i).remove();
// This is a cheap trick to avoid loading sframe-channel in parallel with the
@ -2076,6 +2077,16 @@ define([
cfg.integrationUtils.save(obj, cb);
}
});
sframeChan.on('EV_INTEGRATION_READY', function () {
if (cfg.integrationUtils && cfg.integrationUtils.onReady) {
cfg.integrationUtils.onReady();
}
});
sframeChan.on('EV_INTEGRATION_ON_DOWNLOADAS', function (obj) {
if (cfg.integrationUtils && cfg.integrationUtils.onDownloadAs) {
cfg.integrationUtils.onDownloadAs(obj);
}
});
sframeChan.on('Q_INTEGRATION_HAS_UNSAVED_CHANGES', function (obj, cb) {
if (cfg.integrationUtils && cfg.integrationUtils.onHasUnsavedChanges) {
cfg.integrationUtils.onHasUnsavedChanges(obj, cb);
@ -2089,6 +2100,15 @@ define([
integrationSave = function (cb) {
sframeChan.query('Q_INTEGRATION_NEEDSAVE', null, cb);
};
if (cfg.integrationUtils) {
if (cfg.integrationUtils.setDownloadAs) {
cfg.integrationUtils.setDownloadAs(format => {
sframeChan.event('EV_INTEGRATION_DOWNLOADAS', format);
});
}
}
}
if (cfg.messaging) {

View file

@ -34,6 +34,7 @@ define([
'/common/common-constants.js',
'/components/localforage/dist/localforage.min.js',
'/common/hyperscript.js',
'/common/extensions.js'
], function (
$,
ApiConfig,
@ -64,7 +65,8 @@ define([
Language,
Constants,
localForage,
h
h,
Ext
) {
// Chainpad Netflux Inner
var funcs = {};
@ -775,6 +777,8 @@ define([
return Util.checkRestrictedApp(app, AppConfig, ea, priv.plan, priv.loggedIn);
};
funcs.getExtensions = Ext.getExtensions;
funcs.mailbox = {};
Object.freeze(funcs);

View file

@ -1195,6 +1195,7 @@ MessengerUI, Messages, Pages, PadTypes) {
if (![13,32,46].includes(e.which)) { return; }
e.stopPropagation();
if (e.which === 46) {
$('body').find('.cp-dropdown-content li').first().focus();
return $(el).find('.cp-notification-dismiss').click();
}
$(el).find('.cp-notification-content').click();

View file

@ -407,5 +407,24 @@
"settings_userFeedback": "Активиране на обратната връзка с потребителя",
"settings_deleteTitle": "Изтриване на акаунта",
"settings_deleteHint": "Изтриването на акаунта е окончателно. Вашият CryptDrive и вашият списък с документи ще бъдат изтрити от сървъра. Останалите ви документи ще бъдат изтрити след 90 дни, ако никой друг не ги е съхранил в своя CryptDrive.",
"settings_deleteButton": "Изтриване на акаунта си"
"settings_deleteButton": "Изтриване на акаунта си",
"settings_deleteModal": "Споделете следната информация с вашия администратор на CryptPad, за да бъдат премахнати данните ви от сървъра им.",
"settings_publicSigningKey": "Публичен ключ за подписване",
"settings_deleted": "Вашият потребителски акаунт вече е изтрит. Натиснете OK, за да се върнете на началната страница.",
"settings_anonymous": "Не сте влезли. Настройките тук са специфични за този браузър.",
"settings_logoutEverywhereButton": "Излизане",
"settings_logoutEverywhereTitle": "Затваряне на отдалечената сесия",
"settings_logoutEverywhere": "Принудително излизане от всички други сесии",
"settings_driveDuplicateTitle": "Дубликати на притежавани документи",
"settings_driveDuplicateLabel": "Скриване на дубликатите",
"settings_codeIndentation": "Отстъп при писане на код (интервали)",
"settings_codeUseTabs": "Отстъп с помощта на раздели (вместо интервали)",
"settings_codeFontSize": "Размер на шрифта в редактора за код",
"settings_padWidth": "Максималната ширина на редактора",
"settings_padWidthLabel": "Намалете ширината на редактора",
"settings_padSpellcheckTitle": "Проверка на правописа",
"settings_logoutEverywhereConfirm": "Сигурен ли си? Ще трябва да влезеш на всичките си устройства.",
"settings_driveDuplicateHint": "Когато преместите вашите документи в споделена папка, копие от тях се запазва във вашия CryptDrive, за да се гарантира, контрола ви върху него. Можете да скриете дублираните файлове. Само споделената версия ще бъде видима, освен ако не бъде изтрита, в този случай оригиналът ще се покаже на предишното си място.",
"settings_padWidthHint": "Превключване между режим на страница (по подразбиране), който ограничава ширината на текстовия редактор, и използване на цялата ширина на екрана.",
"settings_padSpellcheckHint": "Тази опция ви позволява да активирате проверка на правописа в документи с форматиран текст. Правописните грешки ще бъдат подчертани в червено и ще трябва да задържите клавиша Ctrl или Meta, докато щраквате с десния бутон, за да видите опциите."
}

View file

@ -534,8 +534,8 @@
"features_f_file1": "Importar i compartir fitxers",
"features_f_reg": "Avantatges dels usuaris/es registrats/des",
"features_f_reg_note": "Amb avantatges addicionals",
"features_f_support": "Suport més ràpid",
"features_f_supporter_note": "Ajudeu a CryptPad a ser financerament viable i demostreu que el programari pot respectar la privadesa i ser finançat voluntàriament pels usuaris",
"features_f_support": "Assistència més ràpida",
"features_f_supporter_note": "Ajudeu el CryptPad a ser econòmicament viable i demostreu que el programari pot respectar la privadesa i ser finançat voluntàriament pels usuaris",
"features_f_storage2_note": "De 5GB a 50GB segons el pla, s'ha augmentat el límit a {0}MB per a les baixades de fitxers",
"features_f_subscribe": "Subscriure's",
"features_f_supporter": "Donar suport a la defensa de la privadesa",
@ -544,7 +544,7 @@
"features_f_storage1": "Emmagatzematge personal ({0})",
"features_f_storage1_note": "Els documents emmagatzemats al vostre CryptDrive no s'eliminen a causa de la inactivitat",
"features_f_register": "Registreu-vos gratuïtament",
"features_f_support_note": "Resposta prioritària de l'equip d'administració per correu electrònic i sistema de tiquets de suport integrat",
"features_f_support_note": "Resposta prioritària de l'equip d'administració per correu electrònic i sistema de tiquets integrat",
"features_f_subscribe_note": "Cal un compte registrat per subscriure's",
"view": "mostra",
"four04_pageNotFound": "No hem pogut trobar la pàgina que cercàveu.",
@ -632,7 +632,7 @@
"form_text_text": "Text",
"form_default": "La teva pregunta aquí?",
"form_type_input": "Text",
"support_cat_abuse": "Informa d'abús",
"support_cat_abuse": "Informa d'un abús",
"form_type_radio": "Elecció",
"broadcast_translations": "Traduccions",
"form_type_sort": "Llista ordenada",
@ -740,7 +740,7 @@
"form_anonAnswer": "Les respostes a aquest formulari són anònimes",
"pad_settings_title": "Configuració del document",
"fc_openIn": "Obre a {0}",
"supportPage": "Suport",
"supportPage": "Assistència",
"fm_filterBy": "Filtre",
"undo": "Desfés",
"support_answer": "Respon",
@ -811,7 +811,7 @@
"autostore_settings": "Podeu activar l'emmagatzematge automàtic de documents a la pàgina <a>Configuració</a>.",
"autostore_store": "Desa",
"autostore_hide": "No ho desis",
"crowdfunding_button": "Doneu suport a CryptPad",
"crowdfunding_button": "Doneu suport al CryptPad",
"settings_codeSpellcheckLabel": "Activa la verificació ortogràfica a l'editor de codi",
"admin_activeSessionsTitle": "Connexions actives",
"admin_registeredTitle": "Usuaris registrats",
@ -894,7 +894,7 @@
"history_fastPrev": "Sessió d'edició anterior",
"history_userNext": "Autor següent",
"snaphot_title": "Instantània",
"unableToDisplay": "No s'ha pogut mostrar el document. Premeu Esc per tornar a carregar la pàgina. Si el problema persisteix, contacteu amb el suport.",
"unableToDisplay": "No s'ha pogut mostrar el document. Premeu Esc per tornar a carregar la pàgina. Si el problema persisteix, contacteu amb l'assistència.",
"admin_archiveButton": "Arxiu",
"register_notes_title": "Notes importants",
"settings_cacheTitle": "Memòria cau",
@ -960,7 +960,7 @@
"fm_link_name_placeholder": "El meu enllaç",
"form_anonName": "El vostre nom",
"fm_link_warning": "Avís: l'URL excedeix els 200 caràcters",
"admin_support_premium": "Tiquets de recompensa:",
"admin_support_premium": "Tiquets prèmium:",
"fm_link_invalid": "URL no vàlid",
"calendar_str_monthly": "{0} mesos",
"form_willClose": "Aquest formulari es tancarà el {0}",
@ -974,7 +974,7 @@
"calendar_rec_yearly_nth": "Cada {0} {1} de {2}",
"calendar_rec_monthly_nth": "Cada {0} {1} del mes",
"calendar_nth_last": "últim",
"admin_cat_support": "Suport",
"admin_cat_support": "Assistència",
"friendRequest_later": "Decideix més tard",
"history_restoreDrivePrompt": "Esteu segur que voleu substituir la versió actual de CryptDrive per la versió mostrada?",
"owner_add": "{0} vol que sigueu propietari del document <b>{1}</b>. Ho accepteu?",
@ -1076,7 +1076,7 @@
"support_cat_drives": "Unitat o equip",
"comments_edited": "Editat",
"comments_submit": "Envia",
"support_debuggingDataHint": "La informació següent s'inclou en els tiquets de suport que envieu. Cap d'ells permet als administradors accedir o desencriptar els vostres documents. Aquesta informació està xifrada de manera que només els administradors poden llegir-la.",
"support_debuggingDataHint": "La informació següent s'inclou en els tiquets d'assistència que envieu. Cap d'ells permet als administradors accedir o desxifrar els vostres documents. Aquesta informació està xifrada de manera que només els administradors poden llegir-la.",
"ui_ms": "mil·lisegons",
"autostore_pad": "document",
"ui_collapse": "Contrau",
@ -1170,24 +1170,24 @@
"autostore_saved": "El document s'ha desat correctament al vostre CryptDrive!",
"autostore_forceSave": "Desa el fitxer al vostre CryptDrive",
"autostore_notAvailable": "Heu de desar aquest document al vostre CryptDrive abans de poder utilitzar aquesta característica.",
"crowdfunding_popup_text": "<h3>Necessitem la vostra ajuda!</h3>Per assegurar que CryptPad es desenvolupa activament, us convidem a donar suport al projecte a través de la pàgina OpenCollective, on podeu veure el nostre <b>Full de ruta</b> i <b>Objectius de finançament</b>.",
"admin_supportInitPrivate": "La vostra instància de CryptPad està configurada per utilitzar una bústia de correu compatible, però el vostre compte no té la clau privada correcta per accedir-hi. Utilitzeu el següent formulari per afegir o actualitzar la clau privada al vostre compte.",
"crowdfunding_popup_text": "<h3>Necessitem la vostra ajuda!</h3>Per assegurar que el CryptPad es desenvolupa activament, us convidem a donar suport al projecte a través de la pàgina OpenCollective, on podeu veure el nostre <b>Full de ruta</b> i <b>Objectius de finançament</b>.",
"admin_supportInitPrivate": "La vostra instància de CryptPad està configurada per utilitzar una bústia de correu d'assistència, però el vostre compte no té la clau privada correcta per accedir-hi. Utilitzeu el següent formulari per afegir o actualitzar la clau privada al vostre compte.",
"admin_supportAddError": "Clau privada no vàlida",
"admin_supportInitTitle": "Permet la inicialització de la bústia de correu",
"admin_supportInitHint": "Podeu configurar una bústia d'assistència per tal de donar als usuaris de la vostra instància de CryptPad una manera de contactar-vos de manera segura si tenen algun problema amb el seu compte.",
"admin_supportListTitle": "Bústia de correu de suport",
"admin_supportListHint": "Aquesta és la llista de tiquets enviats pels usuaris a la bústia de suport. Tots els administradors poden veure els missatges i les seves respostes. No es pot tornar a obrir un bitllet tancat. Només podeu eliminar (amagar) tiquets tancats i els tiquets eliminats encara són visibles per altres administradors.",
"support_disabledTitle": "El suport no està habilitat",
"support_disabledHint": "Aquesta instància de CryptPad encara no està configurada per utilitzar un formulari de suport.",
"admin_supportInitTitle": "Inicialització de la bústia d'assistència",
"admin_supportInitHint": "Podeu configurar una bústia d'assistència per tal de donar als usuaris de la vostra instància de CryptPad una manera de contactar de manera segura si tenen algun problema amb el seu compte.",
"admin_supportListTitle": "Bústia de correu d'assistència",
"admin_supportListHint": "Aquesta és la llista de tiquets enviats pels usuaris a la bústia d'assistència. Tots els administradors poden veure els missatges i les seves respostes. No es pot tornar a obrir un tiquet tancat. Només podeu suprimir (amagar) tiquets tancats i els tiquets eliminats encara són visibles per altres administradors.",
"support_disabledTitle": "L'assistència no està activada",
"support_disabledHint": "Aquesta instància de CryptPad encara no està configurada per a utilitzar un formulari d'assistència.",
"support_cat_new": "Tiquet nou",
"support_formTitle": "Tiquet nou",
"support_formTitleError": "Error: el títol està buit",
"support_formContentError": "Error: el contingut està buit",
"support_cat_tickets": "Tiquets existents",
"support_listTitle": "Tiquets de suport",
"support_listHint": "Aquesta és la llista d'entrades enviades als administradors i les seves respostes. No es pot tornar a obrir un bitllet tancat, però es pot fer un de nou. Podeu amagar els bitllets que s'han tancat.",
"support_listTitle": "Tiquets d'assistència",
"support_listHint": "Aquesta és la llista d'entrades enviades als administradors i les seves respostes. No es pot tornar a obrir un tiquet tancat, però es pot fer un de nou. Podeu amagar els bitllets que s'han tancat.",
"support_close": "Tanca el tiquet",
"support_remove": "Elimina el tiquet",
"support_remove": "Suprimeix el tiquet",
"support_showData": "Mostra/oculta les dades de l'usuari",
"support_from": "<b>De:</b> {0}",
"support_closed": "Aquest tiquet s'ha tancat",
@ -1198,7 +1198,7 @@
"notifications_cat_pads": "Compartit amb mi",
"notifications_cat_archived": "Història",
"notifications_dismissAll": "Descarta-ho tot",
"support_notification": "Un administrador ha respost al vostre tiquet de suport",
"support_notification": "Un administrador ha respost al vostre tiquet d'assistència",
"team_title": "Equip: {0}",
"team_quota": "Límit d'emmagatzematge del vostre equip",
"settings_codeBrackets": "Tanca automàticament els claudàtors",
@ -1412,7 +1412,7 @@
"admin_broadcastButton": "Envia",
"admin_broadcastActive": "Missatge actiu",
"admin_broadcastCancel": "Suprimeix el missatge",
"settings_deleteWarning": "Avís: esteu subscrit a un pla premium (pagat o donat per un altre usuari). Cancel·leu el vostre pla abans d'esborrar el vostre compte, ja que no serà possible sense contactar amb el suport un cop el vostre compte hagi estat eliminat.",
"settings_deleteWarning": "Avís: esteu subscrit a un pla prèmium (pagat o donat per un altre usuari). Cancel·leu el vostre pla abans d'esborrar el vostre compte, ja que no serà possible fer-ho sense contactar amb l'assistència un cop el vostre compte hagi estat eliminat.",
"settings_deleteContinue": "Suprimeix el meu compte",
"oo_cantMigrate": "Aquest full excedeix la mida màxima de càrrega i és massa gran per a ser migrat.",
"calendar_import_temp": "Importa aquest calendari",
@ -1426,13 +1426,13 @@
"reminder_now": "<b>{0}</b> ha començat",
"reminder_minutes": "<b>{0}</b> començarà en {1} minut(s)",
"reminder_time": "<b>{0}</b> avui a {1}",
"oo_conversionSupport": "El navegador no pot gestionar la conversió a i des dels formats ofimàtics. Suggerim utilitzar una versió recent del Firefox o Chrome.",
"oo_conversionSupport": "El navegador no pot gestionar la conversió a i des dels formats ofimàtics. Suggerim que utilitzeu una versió recent del Firefox o Chrome.",
"oo_importBin": "Feu clic a D'acord per a importar el format .bin intern de CryptPad.",
"admin_emailTitle": "Correu electrònic de contacte de l'administrador",
"admin_emailHint": "Establiu aquí el correu electrònic de contacte per a la vostra instància",
"admin_supportPrivTitle": "Dona suport a la clau privada de la bústia",
"admin_supportInitGenerate": "Genera claus de suport",
"admin_supportPrivHint": "Mostra la clau privada que els altres administradors hauran de veure els tiquets de suport. Es mostrarà un formulari per introduir aquesta clau al seu plafó d'administració.",
"admin_supportPrivTitle": "Clau privada de la bústia de correu d'assistència",
"admin_supportInitGenerate": "Genera claus d'assistència",
"admin_supportPrivHint": "Mostra la clau privada que els altres administradors necessitaran per poder veure els tiquets d'assistència. Es mostrarà al panell d'administració un formulari per introduir aquesta clau.",
"admin_supportPrivButton": "Mostra la clau",
"share_formEdit": "Autor",
"form_sort_hint": "Arrossegueu aquests elements des de la majoria (1) fins al mínim ({0}) preferit.",
@ -1499,7 +1499,7 @@
"form_answerAs": "Respon com a",
"ui_expand": "Expandeix",
"form_totalResponses": "Total de respostes: {0}",
"support_premiumPriority": "Els usuaris premium ajuden a millorar la usabilitat de CryptPad i es beneficien de respostes prioritzades als seus bitllets de suport.",
"support_premiumPriority": "Els usuaris prèmium ajuden a millorar la usabilitat de CryptPad i es beneficien de respostes prioritzades als seus tiquets d'assistència.",
"support_premiumLink": "Mostra les opcions de subscripció",
"toolbar_collapse": "Redueix la barra d'eines",
"toolbar_expand": "Expandeix la barra d'eines",
@ -1528,15 +1528,15 @@
"admin_archiveNote": "Nota",
"admin_descriptionHint": "El text descriptiu mostrat per aquesta instància a la llista d'instàncies públiques a cryptpad.org",
"footer_source": "Codi font",
"support_warning_prompt": "Trieu la categoria més rellevant per al vostre problema. Això ajuda als administradors a trigar i proporciona més suggeriments per a quina informació proporcionar",
"support_warning_account": "Tingueu en compte que els administradors no poden restablir les contrasenyes. Si heu perdut les credencials al vostre compte però encara hi esteu connectat, podeu <a>migrar les vostres dades a un compte nou</a>",
"support_warning_drives": "Tingueu en compte que els administradors no poden identificar carpetes i documents per nom. Per a carpetes compartides, proporcioneu un identificador de document <a></a>",
"support_warning_document": "Especifiqueu quin tipus de document està causant el problema i proporcioneu un identificador de document <a></a> o un enllaç",
"support_warning_prompt": "Trieu la categoria més rellevant per al vostre problema. Això ajuda els administradors a prioritzar i proporciona més suggeriments per a quina informació proporcionar",
"support_warning_account": "Tingueu en compte que els administradors no poden restablir les contrasenyes. Si heu perdut les credencials al vostre compte, però encara hi esteu connectat, podeu <a>migrar les vostres dades a un compte nou</a>",
"support_warning_drives": "Tingueu en compte que els administradors no poden identificar carpetes i documents pel seu nom. Per a carpetes compartides, proporcioneu un <a>identificador de document </a>",
"support_warning_document": "Especifiqueu quin tipus de document està causant el problema i proporcioneu un <a>identificador de document </a> o un enllaç",
"calendar_list_end": "{0} o {1}",
"calendar_rec_every_date": "Cada {0}",
"support_warning_bug": "Especifiqueu en quin navegador es produeix el problema i si hi ha instal·lades extensions. Proporcioneu el màxim detall possible sobre el problema i els passos necessaris per reproduir-lo",
"support_warning_abuse": "Informeu del contingut que viola les <a>condicions del servei</a>. Proporcioneu enllaços als documents o perfils d'usuari infractors i descriviu com estan violant els termes. Qualsevol informació addicional sobre el context en què heu descobert el contingut o el comportament pot ajudar els administradors a prevenir futures violacions",
"support_warning_other": "Quina és la naturalesa de la seva consulta? Si us plau, proporcioni la màxima informació rellevant possible per a facilitar-nos que abordem la seva qüestió ràpidament",
"support_warning_other": "Quina és la naturalesa de la vostra consulta? Proporcioneu tanta informació rellevant com us sigui possible per a facilitar-nos la gestió del problema",
"support_cat_document": "Document",
"ui_openDirectly": "Aquesta funcionalitat no està disponible si el CryptPad està incrustat en un altre lloc web. Voleu obrir el document en una pestanya nova?",
"support_cat_debugging": "Depura les dades",
@ -1571,7 +1571,7 @@
"form_editable_on": "Una vegada i edita",
"chrome68": "Sembla que esteu utilitzant el navegador Chrome o Chromium versió 68. Conté un error que fa que la pàgina es torni completament blanca després d'uns segons o que la pàgina no respongui als clics. Per a solucionar aquest problema, podeu canviar a una altra pestanya i tornar enrere, o intentar desplaçar-vos per la pàgina. Aquest error s'ha de corregir en la versió següent del navegador.",
"admin_updateLimitHint": "Forçar una actualització dels límits d'emmagatzematge dels usuaris es pot fer en qualsevol moment, però només és necessari en cas d'error",
"admin_supportInitHelp": "El servidor encara no està configurat per tenir una bústia de correu compatible. Si voleu que una bústia de suport rebi missatges dels vostres usuaris, hauríeu de demanar a l'administrador del servidor que executi l'script ubicat a «./scripts/generate-admin-keys.js», després deseu la clau pública al fitxer «config.js» i envieu la clau privada.",
"admin_supportInitHelp": "El servidor encara no està configurat per tenir una bústia de correu d'assistència. Si voleu que una bústia d'assistència rebi missatges dels vostres usuaris, hauríeu de demanar a l'administrador del servidor que executi l'script ubicat a «./scripts/generate-admin-keys.js», després deseu la clau pública al fitxer «config.js» i envieu la clau privada.",
"support_formHint": "Utilitzeu aquest formulari per contactar amb seguretat amb els administradors sobre problemes i preguntes.<br>Tingueu en compte que alguns problemes/preguntes ja es poden abordar a la <a>Guia d'usuari de CryptPad</a>. No creeu un tiquet nou si ja teniu un tiquet obert sobre el mateix problema. En canvi, responeu al vostre missatge original amb qualsevol informació addicional.",
"requestEdit_confirm": "{1} ha demanat la possibilitat d'editar el document <b>{0}</b>. Voleu concedir l'accés?",
"owner_removedPending": "{0} ha cancel·lat la vostra oferta de propietat de <b>{1}</b>",
@ -1666,5 +1666,56 @@
"status": "Pàgina d'estat",
"admin_diskUsageWarning": "Utilitzeu-ho amb precaució! Depenent de la mida de les dades emmagatzemades a la instància, generar aquest informe pot consumir tota la memòria disponible al servidor i originar una fallada.",
"dph_pad_pw": "El document s'ha protegit amb una contrasenya nova",
"dph_sf_destroyed_team": "Un propietari ha destruït la carpeta compartida <b>{0}</b> a la unitat de l'equip <b>{1}</b>"
"dph_sf_destroyed_team": "Un propietari ha destruït la carpeta compartida <b>{0}</b> a la unitat de l'equip <b>{1}</b>",
"admin_invitationEmail": "Adreça de l'usuari",
"admin_registrationSsoTitle": "Tanca el registre per SSO",
"admin_invitationCreate": "Crea un enllaç d'invitació",
"admin_invitationTitle": "Enllaços d'invitació",
"admin_invitationLink": "Enllaç d'invitació",
"admin_invitationDeleteConfirm": "Segur que voleu eliminar aquesta invitació?",
"admin_usersTitle": "Directori d'usuari",
"admin_invitationCopy": "Copia l'enllaç",
"admin_invitationAlias": "Nom d'usuari",
"admin_usersRemove": "Suprimeix",
"admin_usersAdd": "Afegeix l'usuari conegut",
"admin_usersRemoveConfirm": "Segur que voleu suprimir aquest usuari del directori? Encara podrà accedir i utilitzar el seu compte.",
"admin_storeSsoLabel": "Desa automàticament els usuaris SSO",
"register_invalidToken": "L'enllaç d'invitació no és vàlid",
"ssoauth_header": "Contrasenya CryptPad",
"ssoauth_form_hint_login": "Introduïu la contrasenya CryptPad",
"duplicate": "Duplica",
"calendar_desc": "Descripció",
"calendar_description": "Descripció: {0}{1}",
"sso_login_description": "Inicieu la sessió amb",
"sso_register_description": "Registreu-vos amb",
"kanban_showTags": "Mostra totes les etiquetes",
"kanban_hideTags": "Mostra menys etiquetes",
"admin_forcemfaTitle": "Autenticació de dos factors obligatòria",
"admin_forcemfaHint": "Es demanarà a tots els usuaris de la instància que estableixin una autenticació de dos factors per a iniciar la sessió.",
"calendar_rec_change_first": "S'està movent el primer esdeveniment de la repetició a un calendari diferent. També es mouran tots els esdeveniments repetits.",
"admin_logoTitle": "Logotip personalitzat",
"admin_cat_security": "Seguretat",
"admin_cat_customize": "Personalitza",
"admin_colorTitle": "Color d'èmfasi",
"admin_logoHint": "SVG, PNG o JPG, mida màxima 200 KB",
"admin_logoButton": "Puja el logotip",
"admin_colorHint": "Canvieu el color d'èmfasi de la instància del CryptPad. Comproveu que el text i els botons són llegibles amb prou contrast als temes clars i foscos.",
"admin_logoRemoveButton": "Restableix el predefinit",
"admin_colorCurrent": "Color d'èmfasi actual",
"admin_supportDisabled": "S'ha desactivat el sistema d'assistència.",
"admin_colorChange": "Canvia el color",
"admin_colorPick": "Trieu un color",
"admin_colorPreview": "Previsualització",
"admin_supportSetupHint": "Creeu o actualitzeu les claus d'assistència.",
"admin_supportSetupTitle": "Inicialitza l'assistència",
"admin_supportEnabled": "S'ha activat el sistema d'assistència.",
"admin_supportInit": "Inicialitza el help-desk en aquesta instància",
"admin_cat_users": "Directori d'usuari",
"calendar_rec_change": "S'està movent un esdeveniment repetit a un calendari diferent. Només podeu aplicar el canvi a aquest esdeveniment, o a tots els repetits.",
"loading_mfa_required": "Cal autenticació de dos factors en aquesta instància. Actualitzeu el vostre compte fent servir una aplicació d'autenticació i el formulari de sota.",
"admin_invitationHint": "Els enllaços d'invitació creen un compte cadascú, fins i tot si el registre es troba tancat. El nom d'usuari i l'adreça electrònica només són per poder identificar-vos. El CryptPad no enviarà per correu l'enllaç d'invitació (ni cap altra cosa), copieu-lo i envieu-lo fent servir el canal segur que trieu.",
"admin_usersHint": "Llista dels comptes coneguts d'aquesta instància. Seleccioneu a continuació per a afegir comptes automàticament, o introduïu la informació manualment amb el formulari.",
"admin_usersBlock": "URL de blocatge d'inici de sessió de l'usuari (opcional)",
"ssoauth_form_hint_register": "Afegiu una contrasenya CryptPad per a més seguretat, o deixeu-la buida i continueu. Si no afegiu una contrasenya, els administradors de la instància tindran a l'abast les claus que protegeixen les vostres dades.",
"admin_storeInvitedLabel": "Desa automàticament els usuaris convidats"
}

View file

@ -1019,7 +1019,7 @@
"admin_getlimitsTitle": "Individuelle Regeln",
"admin_limit": "Aktuelle Begrenzung: {0}",
"admin_defaultlimitHint": "Speicherplatzbegrenzung für CryptDrives (Benutzer und Teams), sofern keine individuelle Regel festgelegt wurde",
"admin_registrationHint": "Erlaube keine neuen Benutzerregistrierungen",
"admin_registrationHint": "Besucher der Instanz können keine Accounts erstellen. Einladungen können von Administratoren erstellt werden.",
"admin_cat_quota": "Speicher für Benutzer",
"admin_invalLimit": "Wert für Speicherplatzbegrenzung ist ungültig",
"admin_limitSetNote": "Notiz",
@ -1668,7 +1668,7 @@
"admin_diskUsageWarning": "Mit Vorsicht zu verwenden! Je nach Größe der auf der Instanz gespeicherten Daten kann die Erstellung dieses Berichts den gesamten auf dem Server verfügbaren Speicher verbrauchen und zu einem Absturz führen.",
"dph_sf_destroyed": "Geteilter Ordner <b>{0}</b> wurde vom Eigentümer zerstört",
"calendar_desc": "Beschreibung",
"admin_forcemfaHint": "Alle Benutzer dieser Instanz werden aufgefordert, eine Zwei-Faktor-Authentifizierung für die Anmeldung bei ihrem Account einzurichten.",
"admin_forcemfaHint": "Alle Benutzer dieser Instanz werden aufgefordert, eine Zwei-Faktor-Authentifizierung für die Anmeldung bei ihrem Account einzurichten. Beachte, dass bestehende Benutzer nicht in der Lage sein werden, ihren Account weiterhin zu nutzen, ohne eine TOTP-Anwendung einzurichten.",
"ssoauth_form_hint_register": "Füge ein CryptPad-Passwort für zusätzliche Sicherheit hinzu oder lasse es leer und fahre fort. Wenn du kein Passwort hinzufügst, können die Administratoren der Instanz auf die Schlüssel zum Schutz deiner Daten zugreifen.",
"ssoauth_form_hint_login": "Bitte gib dein CryptPad-Passwort ein",
"loading_mfa_required": "Auf dieser Instanz ist eine Zwei-Faktor-Authentifizierung erforderlich. Bitte aktualisiere deinen Account mit einer Authentifizierungs-App und dem folgenden Formular.",
@ -1763,5 +1763,22 @@
"support_movePending": "In das Archiv verschieben",
"support_cat_legacy": "Alte Daten",
"support_legacyTitle": "Alte Support-Daten ansehen",
"support_userNotification": "Neues Support-Ticket oder neue Antwort: {0}"
"support_userNotification": "Neues Support-Ticket oder neue Antwort: {0}",
"install_token": "Installations-Token",
"install_header": "Installation",
"admin_appSelection": "Konfiguration der Anwendungen",
"install_launch": "Einrichtung der Instanz",
"install_instance": "Erstelle den ersten Admin-Account und fahre dann mit der Anpassung dieser Instanz fort",
"admin_appsTitle": "Anwendungen der Instanz",
"onboarding_save_error": "Einige Einstellungen konnten nicht korrekt gespeichert werden. Bitte besuche den Administrationsbereich, um die Werte zu überprüfen.",
"admin_appsHint": "Wähle aus, welche Anwendungen auf dieser Instanz aktiviert werden sollen.",
"admin_cat_apps": "Anwendungen",
"admin_onboardingNameTitle": "Willkommen auf deiner CryptPad-Instanz",
"install_notes": "<ul class=\"cp-notes-list\"><li>Erstelle auf dieser Seite deinen ersten Administrator-Account. Administratoren verwalten die Einstellungen der Instanz einschließlich der Speicherplatzkontingente und haben Zugriff auf die Moderationswerkzeuge.</li><li>Dein Passwort ist der geheime Schlüssel, der alle deine Dokumente und Administratorrechte auf dieser Instanz verschlüsselt. <span class=\"red\">Wenn du es verlierst, gibt es keine Möglichkeit, deine Daten wiederherzustellen.</span></li><li>Wenn du einen gemeinsam genutzten Computer verwendest, <span class=\"red\">denke daran, dich abzumelden,</span> wenn du fertig bist. Wird das Browserfenster einfach geschlossen, bleibt dein Account zugänglich.</li></ul>",
"onboarding_upload": "Logo auswählen",
"admin_onboardingOptionsTitle": "Einstellungen der Instanz",
"admin_onboardingNamePlaceholder": "Name der Instanz",
"admin_onboardingDescPlaceholder": "Beschreibungstext für die Instanz",
"admin_onboardingOptionsHint": "Bitte wähle die geeignete Option für deine Instanz.<br>Diese Einstellungen können später im Administrationsbereich geändert werden.",
"admin_onboardingNameHint": "Bitte wähle einen Namen, eine Beschreibung, eine Akzentfarbe und ein Logo (alle Angaben sind optional)"
}

View file

@ -1733,5 +1733,35 @@
"support_closed_tag": "Itxita",
"support_privacyTitle": "Erantzun anonimoki",
"moderationPage": "Laguntza mahaia",
"admin_supportInit": "Hasieratu laguntza mahaia instantzia honetan"
"admin_supportInit": "Hasieratu laguntza mahaia instantzia honetan",
"support_openTicketTitle": "Ireki txartel bat erabiltzaile batekin",
"support_privacyHint": "Markatu aukera hau zure erabiltzaile-izenaren ordez \"Laguntza-taldea\" gisa erantzuteko",
"support_notificationsHint": "Markatu aukera hau txartel eta erantzun berrien jakinarazpenak desgaitzeko",
"support_notificationsTitle": "Desgaitu jakinarazpenak",
"support_recordedEmpty": "Kode-zatirik ez",
"support_userChannel": "Erabiltzailearen jakinarazpenen kanalaren IDa",
"support_openTicketHint": "Kopiatu hartzailearen erabiltzailearen datuak bere profil-orritik edo lehendik dagoen laguntza-txartel batetik. Mezu honi buruzko CryptPad jakinarazpena jasoko dute.",
"support_recordedId": "Kode-zatiaren ID (esklusiboa)",
"support_userKey": "Erabiltzailearen gako publikoa",
"support_invalChan": "Jakinarazpen-kanal baliogabea",
"support_recordedTitle": "Kode-zatiak",
"admin_supportTeamTitle": "Kudeatu laguntza taldea",
"support_pasteUserData": "Itsatsi erabiltzailearen datuak hemen",
"support_legacyButton": "Lortu txartel aktiboak",
"support_recordedHint": "Gorde testu arrunta klik bakarreko lasterbide gisa laguntza-mezuetan txertatzeko.",
"support_recordedContent": "Edukia",
"support_legacyTitle": "Ikusi laguntza-datu zaharrak",
"support_searchLabel": "Bilatu (titulua edo txartelaren ID)",
"support_legacyHint": "Ikusi laguntza sistema zaharraren txartelak eta berrerabili berrian.",
"support_legacyDump": "Esportatu guztiak",
"support_insertRecorded": "Txertatu kode-zatia",
"support_legacyClear": "Ezabatu kontu honetarako",
"support_moveActive": "Eraman aktibora",
"support_team": "Laguntza taldea",
"support_answerAs": "<b>{0}</b> gisa erantzuten",
"support_movePending": "Eraman artxibora",
"admin_supportOpen": "Ireki laguntza tresnak",
"support_copyUserData": "Kopiatu erabiltzailearen datuak",
"support_userNotification": "Laguntza-txartel edo erantzun berria: {0}",
"admin_supportTeamHint": "Gehitu eta kendu jendea instantziako laguntza-taldetik"
}

View file

@ -1018,7 +1018,7 @@
"admin_defaultlimitTitle": "Limite de stockage (Mo)",
"admin_defaultlimitHint": "Limite de stockage maximum pour le CryptDrive (utilisateur·ices et équipes) si aucune règle spéciale n'est appliquée",
"admin_registrationTitle": "Fermer l'enregistrement",
"admin_registrationHint": "Ne pas autoriser l'enregistrement de nouvelles·aux utilisateur·ices",
"admin_registrationHint": "Les visiteur·ices de l'instance ne sont pas autorisé·es à créer un compte. Des invitations peuvent être créées par les administrateur·ices.",
"snapshots_cantMake": "La capture n'a pas pu être effectuée. Vous êtes déconnecté.",
"snapshots_notFound": "Cette capture n'existe plus car l'historique du document a été supprimé.",
"admin_limitUser": "Clé publique de l'utilisateur·ice",
@ -1680,7 +1680,7 @@
"kanban_showTags": "Voir tous les mots-clés",
"kanban_hideTags": "Voir moins de mots-clés",
"admin_forcemfaTitle": "Authentification à deux facteurs obligatoire",
"admin_forcemfaHint": "Tous les utilisateurs de cette instance seront obligés d'activer l'authentification à deux facteurs pour se connecter à leur compte.",
"admin_forcemfaHint": "Tou·tes les utilisateur·ices de l'instance devront activer l'authentification a deux facteurs (2FA) pour pouvoir se connecter à leur compte. Notez que les utilisateur·ices existant·es ne pourront pas continuer à utiliser leur compte sans mettre en place une application TOTP.",
"loading_mfa_required": "L'authentification à deux facteurs est requise pour cette instance. Veuillez mettre à jour votre compte en utilisant une application d'authentification et le formulaire ci-dessous.",
"admin_cat_users": "Registre utilisateur·ices",
"admin_invitationCreate": "Créer un lien d'invitation",
@ -1706,7 +1706,7 @@
"admin_logoTitle": "Logo personnalisé",
"admin_supportAdd": "Ajouter un contact à l'équipe support",
"admin_logoHint": "SVG, PNG ou JPG, taille maximum 200 kB",
"admin_logoRemoveButton": "Logo par défaut",
"admin_logoRemoveButton": "Réinitialiser",
"admin_colorCurrent": "Couleur d'accent actuelle",
"admin_colorChange": "Changer la couleur",
"admin_colorPick": "Choisir une couleur",
@ -1763,5 +1763,22 @@
"support_openTicketHint": "Copiez les données de l'utilisateur·ices destinataire depuis leur page de profil ou depuis un ticket de support existant. Iels recevront une notification CryptPad à propos de ce message.",
"support_invalChan": "Canal de notifications invalide",
"support_legacyHint": "Voir les tickets de l'ancien système de support et les recréer dans le nouveau.",
"support_userNotification": "Nouveau ticket de support ou réponse : {0}"
"support_userNotification": "Nouveau ticket de support ou réponse : {0}",
"install_token": "Jeton d'installation",
"install_header": "Installation",
"admin_appSelection": "Configuration des applications",
"install_instance": "Créer le premier compte administrateur·ice, puis continuer pour personnaliser l'instance",
"install_launch": "Paramétrage de l'instance",
"admin_appsTitle": "Applications de l'instance",
"admin_appsHint": "Choisissez quelles applications sont activées sur cette instance.",
"admin_cat_apps": "Applications",
"onboarding_upload": "Sélectionner un logo",
"onboarding_save_error": "Certaines options n'ont pas pu être sauvegardées correctement. Veuillez visiter l'espace d'administration pour vérifier les valeurs indiquées.",
"admin_onboardingNameHint": "Veuillez choisir un titre, une description, une couleur de thème et un logo (tous sont optionnels)",
"admin_onboardingNameTitle": "Bienvenu sur votre instance CryptPad",
"admin_onboardingOptionsTitle": "Réglages de l'instance",
"admin_onboardingNamePlaceholder": "Nom de l'instance",
"admin_onboardingOptionsHint": "Veuillez sélectionner les options appropriées pour votre instance.<br>Ces paramètres peuvent être changés plus tard depuis l'espace d'administration.",
"admin_onboardingDescPlaceholder": "Texte de description de l'instance",
"install_notes": "<ul class=\"cp-notes-list\"><li>Créez votre premier compte administrateur·ice sur cette page. Les administrateur·ices peuvent paramétrer l'instance, ceci incluant les quotas de stockage, et ont accès aux outils de modération.</li><li>Votre mot de passe est la clé secrète qui chiffre l'ensemble de vos documents et vos privilèges d'administration sur l'instance. <span class=\"red\">Si vous le perdez il n'est pas possible de récupérer vos données.</span></li><li>Si vous utilisez un ordinateur partagé, <span class=\"red\">n'oubliez pas de vous déconnecter</span> quand vous aurez terminé. Simplement fermer la fenêtre du navigateur web laisse votre compte exposé à des risques de sécurité. </li></ul>"
}

View file

@ -682,7 +682,7 @@
"crowdfunding_popup_text": "<h3>Kami butuh bantuan Anda</h3>Untuk memastikan CryptPad dikembangkan secara aktif, pertimbangkan mendukung proyek ini melalui laman OpenCollective, di mana Anda dapat melihat <b>Peta jalan</b> dan <b>Sasaran pendanaan</b>.",
"admin_activeSessionsHint": "Jumlah koneksi WebSocket aktif (dan alamat IP unik yang terhubung)",
"admin_updateLimitHint": "Memperbarui pembaruan batasan penyimpanan pengguna secara paksa dapat dilakukan kapan pun, tetapi hanya perlu jika ada kesalahan",
"admin_flushCacheHint": "Paksa pengguna untuk mengunduh aset sisi klien terbaru (hanya jika server Anda dalam mode segar)",
"admin_flushCacheHint": "Paksa semuapengguna untuk mengunduh aset terkini setelah perubahan kustomisasi atau konfigurasi. Menghindari memulai ulang server tetapi membuat semua pengguna mengatur ulang koneksinya, silakan gunakan sesuai kebutuhan.",
"contact_devHint": "Untuk permintaan fitur, peningkatan penggunaan, atau untuk berterima kasih.",
"timeoutError": "Sebuah kesalahan telah memutuskan koneksi Anda ke server. <br>Tekan Esc untuk memuat ulang laman.",
"profile_info": "Pengguna lain dapat menemukan profil Anda melalui avatar Anda di daftar pengguna dokumen.",
@ -1412,7 +1412,7 @@
"team_inviteLinkError": "Terjadi kesalahan saat membuat tautan.",
"info_imprintFlavour": "<a>Informasi legal</a> tentang administrator server ini",
"snapshot_error_exists": "Sudah ada snapshot dari versi ini",
"admin_registrationHint": "Jangan perbolehkan pengguna baru untuk mendaftar",
"admin_registrationHint": "Tamu server tidak dapat membuat akun. Undangan dapat dibuat oleh administrator.",
"admin_unarchiveHint": "Pulihkan dokumen yang sebelumnya diarsip",
"broadcast_newSurvey": "Sebuah survei baru telah tersedia. Klik untuk membuka.",
"mfa_status_off": "2FA belum aktif di akun ini",
@ -1667,7 +1667,7 @@
"admin_broadcastHint": "Kirimkan pesan ke semua pengguna di server ini. Semua pengguna yang sudah ada dan pengguna baru akan menerimanya sebagai notifikasi. Tampilkan pesan sebelum dikirimkan dengan \"Tampilkan notifikasi\". Notifikasi yang ditampilkan memiliki ikon merah dan hanya tersedia untuk Anda.",
"support_warning_abuse": "Mohon laporkan konten yang melanggar <a>Ketentuan Layanan</a>. Mohon sediakan tautan ke dokumen atau profil pengguna yang melanggar dan jelaskan bagaimana mereka melanggar ketentuannya. Informasi tambahan dalam konteks yang Anda mengetahui konten atau perilaku dapat membantu administrator mencegah pelanggaran di masa depan",
"safeLinks_error": "Tautan ini disalin dari bilah alamat peramban dan tidak menyediakan akses ke dokumen. Silakan gunakan menu <i></i> <b>Bagikan</b> untuk membagikan ke kontak secara langsung atau salin tautannya. <a>Baca lebih lanjut tentang fitur Tautan Aman</a>.",
"admin_cat_users": "Direktori Pengguna",
"admin_cat_users": "Direktori pengguna",
"admin_invitationCreate": "Buat tautan undangan",
"admin_registrationSsoTitle": "Tutup pendaftaran SSO",
"admin_invitationTitle": "Tautan undangan",
@ -1680,7 +1680,7 @@
"admin_usersRemove": "Hapus",
"admin_invitationEmail": "Surel pengguna",
"admin_storeInvitedLabel": "Simpan pengguna yang diundang secara otomatis",
"admin_forcemfaHint": "Semua pengguna di server ini akan diminta untuk menyiapkan autentikasi dua faktor untuk masuk ke akun mereka.",
"admin_forcemfaHint": "Semua pengguna di server ini akan diminta untuk menyiapkan autentikasi dua faktor untuk masuk ke akun mereka. Pengguna yang sudah ada tidak akan dapat tetap menggunakan akunnya tanpa menyiapkan aplikasi TOTP.",
"admin_invitationHint": "Setiap tautan undangan membuat satu akun, bahkan jika pendaftaran ditutup. Nama pengguna dan surel hanya untuk keperluan identifikasi Anda. CryptPad tidak akan mengirim surel berisi tautan undangan (atau yang lain), mohon salin tautan dan kirimkan melalui saluran aman pilihan Anda.",
"calendar_rec_change_first": "Memindahkan pengulangan pertama ke kalender lain. Semua kejadian yang berulang juga akan dipindahkan.",
"admin_invitationCopy": "Salin tautan",
@ -1735,5 +1735,50 @@
"support_notificationsTitle": "Nonaktifkan notifikasi",
"moderationPage": "Ruang bantuan",
"admin_supportInit": "Mulai ruang bantuan di server ini",
"admin_supportRotateNotify": "Peringatan: kunci baru telah dibuat tetapi ada kesalahan yang tidak terduga yang mencegah sistem untuk mengirimnya kepada para moderator. Silakan hapus dan tambahkan lagi semua anggota tim bantuan"
"admin_supportRotateNotify": "Peringatan: kunci baru telah dibuat tetapi ada kesalahan yang tidak terduga yang mencegah sistem untuk mengirimnya kepada para moderator. Silakan hapus dan tambahkan lagi semua anggota tim bantuan",
"support_openTicketTitle": "Buka tiket dengan pengguna",
"support_notificationsHint": "Centang opsi ini untuk menonaktifkan notifikasi untuk tiket dan balasan baru",
"support_userChannel": "ID saluran notifikasi pengguna",
"support_openTicketHint": "Salin data pengguna penerima dari laman profilnya atau tiket dukungan yang sudah ada. Mereka akan menerima notifikasi CryptPad tentang pesan ini.",
"support_recordedId": "ID potongan (unik)",
"support_userKey": "Kunci publik pengguna",
"support_recordedTitle": "Potongan",
"support_invalChan": "Saluran notifikasi tidak valid",
"admin_supportTeamTitle": "Kelola tim dukungan",
"support_pasteUserData": "Tempelkan data pengguna di sini",
"admin_supportTeamHint": "Tambahkan atau keluarkan orang dari tim dukungan server",
"support_legacyButton": "Dapatkan tiket aktif",
"support_recordedHint": "Simpan teks umum sebagai pintasan sekali klik untuk disisipkan dalam pesan dukungan.",
"support_recordedContent": "Konten",
"support_recordedEmpty": "Tidak ada potongan",
"support_legacyTitle": "Tampilkan data dukungan lama",
"support_searchLabel": "Cari (judul atau ID tiket)",
"support_legacyHint": "Lihat tiket dari sistem dukungan lawas dan buat ulang dalam yang baru.",
"support_legacyDump": "Ekspor semua",
"support_insertRecorded": "Sisipkan potongan",
"support_legacyClear": "Hapus untuk akun ini",
"support_team": "Tim Dukungan",
"support_answerAs": "Menjawab sebagai <b>{0}</b>",
"support_movePending": "Pindahkan ke arsip",
"admin_supportOpen": "Buka pusat bantuan",
"support_moveActive": "Pindahkan ke aktif",
"support_copyUserData": "Salin data pengguna",
"support_userNotification": "Tiket atau respons dukungan baru: {0}",
"install_header": "Pemasangan",
"install_token": "Token pemasangan",
"admin_appSelection": "Konfigurasi aplikasi",
"install_instance": "Buat akun admin pertama, terus lanjut mengubah server",
"install_launch": "Penyiapan server",
"admin_appsTitle": "Aplikasi server",
"admin_appsHint": "Pilih aplikasi apa saja untuk diaktifkan di server ini.",
"admin_cat_apps": "Aplikasi",
"onboarding_upload": "Pilih logo",
"onboarding_save_error": "Beberapa opsi tidak dapat disimpan dengan benar. Silakan kunjungi panel administrasi untuk memeriksa nilai.",
"admin_onboardingNameHint": "Silakan pilih nama, deskripsi, warna aksen, dan logo (semua bersifat opsional)",
"admin_onboardingNameTitle": "Selamat datang di server CryptPad Anda",
"admin_onboardingOptionsTitle": "Opsi server",
"admin_onboardingNamePlaceholder": "Judul server",
"admin_onboardingDescPlaceholder": "Teks deskripsi server",
"admin_onboardingOptionsHint": "Silakan pilih opsi sesuai untuk server Anda.<br>Pengaturan ini dapat diubah lagi dalam panel admin.",
"install_notes": "<ul class=\"cp-notes-list\"><li>Buat akun administrator Anda yang pertama di laman ini. Administrator mengelola pengaturan server termasuk kuota penyimpanan dan memiliki akses ke peralatan moderasi.</li><li>Kata sandi Anda adalah kunci rahasia yang mengenkripsi semua dokumen dan hak administrator Anda di server ini.<span class=\"red\">Jika Anda kehilangan kata sandi tersebut, kami tidak dapat memulihkan data Anda.</span></li><li>Jika Anda menggunakan komputer terbagi, <span class=\"red\">jangan lupa untuk keluar dari akun</span> setelah Anda selesai. Hanya menutup jendela peramban membuat akun Anda rentan.</li></ul>"
}

View file

@ -13,7 +13,7 @@
"todo": "Promemoria",
"contacts": "Contatti",
"sheet": "Foglio",
"teams": "Team",
"teams": "Gruppi",
"presentation": "Presentazione",
"doc": "Documento",
"form": "Modulo",
@ -253,8 +253,8 @@
"fm_folder": "Cartella",
"fm_sharedFolder": "Cartella condivisa",
"fm_folderName": "Nome della cartella",
"fm_numberOfFolders": "Numero di cartelle",
"fm_numberOfFiles": "Numero di file",
"fm_numberOfFolders": "N° di cartelle",
"fm_numberOfFiles": "N° di file",
"fm_fileName": "Nome del file",
"fm_type": "Tipo",
"fm_lastAccess": "Ultimo accesso",
@ -469,7 +469,7 @@
"features_f_subscribe": "Abbonati",
"features_f_supporter_note": "Aiuta CryptPad a diventare finanziariamente sostenibile e a dimostrare che i software che proteggono la privacy, finanziati volontariamente dagli utenti e dalle utenti, devono essere la norma",
"features_f_supporter": "Sostieni la privacy",
"features_f_support_note": "Risposta prioritaria da parte del team di amministrazione via email e sistema per le richieste di assistenza integrato",
"features_f_support_note": "Risposta prioritaria da parte della squadra di amministrazione via email e sistema per le richieste di assistenza integrato",
"features_f_storage2_note": "Da 5GB a 50GB in funzione del piano selezionato, limite aumentato di {0}MB per il caricamento di file",
"features_f_storage2": "Spazio di archiviazione aggiuntivo",
"features_f_reg_note": "Con ulteriori vantaggi",
@ -515,7 +515,7 @@
"upload_modal_owner": "File di tua proprietà",
"upload_modal_filename": "Nome del file (estensione <em>{0}</em> aggiunta automaticamente)",
"settings_cursorShowHint": "Puoi decidere di visualizzare la posizione del cursore degli altri utenti e delle altre utenti nei documenti collaborativi.",
"settings_cursorShareHint": "Puoi decidere di mostrare la posizione del tuo cursore agli altri utenti e alle altri utenti nei documenti collaborativi.",
"settings_cursorShareHint": "Puoi decidere di mostrare la posizione del tuo cursore agli altri utenti e alle altre utenti nei documenti collaborativi.",
"settings_cursorColorHint": "Cambia il colore associato al tuo account nei documenti collaborativi.",
"settings_changePasswordPending": "La tua password è in fase di modifica. Non chiudere o ricaricare questa pagina fino al completamento del processo.",
"settings_changePasswordError": "Si è verificato un errore. Se non riesci ad accedere o cambiare la tua password contatta il tuo amministratore o la tua amministratrice di CryptPad.",
@ -549,7 +549,7 @@
"kanban_color": "Colore",
"kanban_body": "Contenuto",
"kanban_title": "Titolo",
"teams": "Team",
"teams": "Gruppi",
"contacts": "Contatti",
"restrictedError": "Non sei autorizzato/a ad accedere a questo documento",
"access_allow": "Lista",
@ -563,9 +563,9 @@
"team_inviteInvalidLinkError": "Il link d'invito non è valido.",
"team_links": "Link d'invito",
"team_cat_link": "Link d'invito",
"team_inviteJoin": "Unisciti al team",
"team_inviteJoin": "Entra nel gruppo",
"team_invitePleaseLogin": "Accedi o registrati per accettare questo invito.",
"team_inviteFromMsg": "{0} ti ha invitato ad unirti al team <b>{1}</b>",
"team_inviteFromMsg": "{0} ti ha invitato ad entrare nel gruppo <b>{1}</b>",
"team_inviteFrom": "Da:",
"team_inviteLinkCopy": "Copia link",
"team_inviteLinkCreate": "Crea link",
@ -573,30 +573,30 @@
"team_inviteLinkNote": "Aggiungi un messaggio personalizzato",
"pad_wordCount": "Parole: {0}",
"teams_table_role": "Ruolo",
"teams_table_owners": "Gestisci team",
"teams_table_admins": "Gestisci membri",
"teams_table_owners": "Gestisci il gruppo",
"teams_table_admins": "Gestisci i membri",
"teams_table_specific": "Eccezioni",
"teams_table_generic": "Ruoli e permessi",
"teams_table": "Ruoli",
"properties_passwordSuccessFile": "La password è stata cambiata con successo.",
"drive_sfPasswordError": "Password errata",
"team_title": "Team: {0}",
"team_title": "Gruppo: {0}",
"team_pendingOwner": "(in attesa)",
"team_deleteButton": "Elimina",
"team_pending": "Invitato/a",
"sent": "Messaggio inviato",
"team_listTitle": "I tuoi team",
"team_listTitle": "I tuoi gruppi",
"team_avatarHint": "Dimensione massima 500 kB (png, jpg, jpeg, gif)",
"team_avatarTitle": "Immagine del team",
"team_nameHint": "Imposta il nome del team",
"team_nameTitle": "Nome del team",
"team_avatarTitle": "Immagine del gruppo",
"team_nameHint": "Imposta il nome del gruppo",
"team_nameTitle": "Nome del gruppo",
"team_members": "Membri",
"team_leaveButton": "Lascia questo team",
"team_createName": "Nome del team",
"team_createLabel": "Crea un nuovo team",
"team_leaveButton": "Esci da questo gruppo",
"team_createName": "Nome del gruppo",
"team_createLabel": "Crea un nuovo gruppo",
"team_cat_chat": "Chat",
"team_cat_members": "Membri",
"team_cat_list": "Team",
"team_cat_list": "Gruppi",
"team_inviteModalButton": "Invita",
"owner_unknownUser": "sconosciuto/a",
"owner_removePendingText": "In attesa",
@ -645,7 +645,7 @@
"drive_active1Day": "Ultime 24 ore",
"contact_email": "Email",
"contact_chat": "Chat",
"contact_dev": "Contatta il team di sviluppo",
"contact_dev": "Contatta la quadra di sviluppo",
"contact_admin": "Contatta gli amministratori e le amministratrici per: {0}",
"footer_donate": "Dona",
"admin_registeredTitle": "Utenti registrati",
@ -700,7 +700,7 @@
"notifications_cat_friends": "Richieste di contatto",
"notifications_dismissAll": "Ignora tutte",
"team_cat_create": "Nuovo",
"team_cat_back": "Torna ai team",
"team_cat_back": "Torna ai gruppi",
"contacts_unmute": "Riattiva",
"contacts_mutedUsers": "Account silenziati",
"creation_noOwner": "Nessun/a proprietario/a",
@ -797,14 +797,14 @@
"burnAfterReading_warningAccess": "Questo documento è impostato per l'autodistruzione. Cliccando sul pulsante qui sotto vedrai il contenuto una sola volta prima che sia eliminato in modo permanente. Una volta visto il contenuto chiudendo questa finestra perderai l'accesso al documento. Se non sei sicuro/a di voler continuare puoi chiudere questa finestra adesso e riaprirla più tardi.",
"burnAfterReading_warningLink": "Il documento è impostato per l'autodistruzione. Quando il destinatario o la destinataria visiterà questo link, potrà vedere il documento una sola volta prima che questo sia eliminato in modo permanente.",
"team_inviteLinkErrorName": "Aggiungi un nome per la persona che stai invitando. Potrà essere cambiarlo in seguito. ",
"team_inviteLinkNoteMsg": "Questo messaggio verrà mostrato prima che il destinatario o la destinataria decida di unirsi a questo team.",
"team_inviteLinkNoteMsg": "Questo messaggio verrà mostrato prima che il destinatario o la destinataria decida di entrare nel gruppo.",
"share_noContactsNotLoggedIn": "Accedi o registrati per vedere i tuoi contatti esistenti e aggiungerne di nuovi.",
"share_noContactsLoggedIn": "Non hai ancora aggiunto nessuno/a ai tuoi contatti su CryptPad. Condividi il link al tuo profilo per permettere ad altre persone di inviarti richieste di contatto.",
"share_embedPasswordAlert": "Questo elemento è protetto da una password. Quando incorpori questo documento ai visualizzatori ed alle visualizzatrici sarà richiesta la password.",
"share_linkPasswordAlert": "Questo elemento è protetto da una password. Quando spedirai il link il destinatario o la destinataria dovrà inserire la password.",
"share_linkWarning": "Questo link contiene la chiave per il tuo documento. Le persone destinatarie avranno un accesso non revocabile al suo contenuto.",
"teams_table_specificHint": "In queste cartelle condivise (che sono di una versione precedente) i visualizzatori e le visualizzatrici possono modificare i documenti esistenti. I documenti creati o copiati in queste cartelle avranno i permessi standard.",
"teams_table_generic_own": "Gestione del team: modifica il nome e l'immagine del team, aggiungi o rimuovi i suoi proprietari o le sue proprietarie, oppure elimina il team.",
"teams_table_generic_own": "Gestione del gruppo: modifica il nome e l'immagine del gruppo, aggiungi o rimuovi i suoi proprietari o le sue proprietarie, oppure elimina il gruppo.",
"teams_table_generic_edit": "Modifica: crea, modifica ed elimina cartelle e documenti.",
"teams_table_generic_view": "Visualizzazione: accedi a cartelle e documenti (sola lettura).",
"driveOfflineError": "La tua connessione a CryptPad è stata persa. Le modifiche apportate a questo documento non saranno salvate nel tuo CryptDrive. Chiudi tutte le tue schede di CryptPad e riprova in una nuova finestra. ",
@ -815,27 +815,27 @@
"settings_codeBrackets": "Chiudi automaticamente le parentesi",
"team_demoteMeConfirm": "Stai per rinunciare ai tuoi diritti. Questa azione non può essere annullata. Vuoi proseguire?",
"team_pendingOwnerTitle": "Questo amministratore o questa amministratrice non ha ancora accettato la proposta di diventare proprietario/a.",
"team_deleteConfirm": "Stai per eliminare i dati di un intero team. Questo può influire sull'accesso degli altri membri del team ai propri dati. L'eliminazione è irreversibile. Sei sicuro/a di voler continuare?",
"team_kickConfirm": "{0} saprà che l'hai eliminato/a dal team. Sei sicuro/a?",
"team_ownerConfirm": "I co-proprietari e le co-proprietarie possono modificare o eliminare il team e rimuoverti come proprietario/a. Vuoi continuare?",
"owner_team_add": "{0} propone tu sia proprietario/a del team <b>{1}</b>. Accetti?",
"team_maxTeams": "Ogni utente può essere membro di {0} team al massimo.",
"team_listSlot": "Posizione disponibile per un nuovo team",
"team_deleteConfirm": "Stai per eliminare i dati di un intero gruppo. Questo può influire sull'accesso degli altri membri del gruppo ai propri dati. L'eliminazione è irreversibile. Sei sicuro/a di voler continuare?",
"team_kickConfirm": "{0} saprà che l'hai rimosso/a dal gruppo. Sei sicuro/a?",
"team_ownerConfirm": "I co-proprietari e le co-proprietarie possono modificare o eliminare il gruppo e rimuoverti come proprietario/a. Vuoi continuare?",
"owner_team_add": "{0} propone tu sia proprietario/a del gruppo <b>{1}</b>. Accetti?",
"team_maxTeams": "Ogni utente può essere membro di {0} gruppi al massimo.",
"team_listSlot": "Posizione disponibile per un nuovo gruppo",
"team_rosterPromoteOwner": "Proponi di diventare proprietario/a",
"team_deleteTitle": "Eliminazione del team",
"team_deleteHint": "Elimina il team e tutti i documenti di sua esclusiva proprietà.",
"team_quota": "Il limite dello spazio di archiviazione del tuo team",
"team_deleteTitle": "Elimina il gruppo",
"team_deleteHint": "Elimina il gruppo e tutti i documenti di sua esclusiva proprietà.",
"team_quota": "Il limite dello spazio di archiviazione del tuo gruppo",
"properties_passwordWarningFile": "La password è stata modificata con successo ma non è stato possibile aggiornare il tuo CryptDrive con i nuovi dati. Potrebbe essere necessario rimuovere la vecchia versione del file manualmente.",
"teams_table_generic_admin": "Gestione dei membri: invita e rimuovi membri, modifica il ruolo dei membri fino a quello di amministratore/trice.",
"share_contactPasswordAlert": "Questo elemento è protetto da una password. Siccome lo stai condividendo con un contatto CryptPad, il destinatario o la destinataria non dovrà inserire la password.",
"share_copyProfileLink": "Copia il link del profilo",
"team_inviteLinkTitle": "Crea un invito personalizzato per questo team",
"team_inviteLinkTitle": "Crea un invito personalizzato per questo gruppo",
"team_inviteLinkSetPassword": "Proteggi il link con una password (consigliato)",
"team_inviteLinkTempName": "Nome temporaneo (visibile nella lista degli inviti in attesa)",
"team_inviteLinkWarning": "Le persone che accedono a questo link potranno unirsi al team e vedere i suoi contenuti. Condividilo con prudenza.",
"team_inviteLinkWarning": "Le persone che accedono a questo link potranno entrare nel gruppo e vedere i suoi contenuti. Condividilo con prudenza.",
"team_invitePasswordLoading": "Decriptazione dell'invito in corso",
"team_inviteGetData": "Ricezione di dati del team in corso",
"team_inviteTitle": "Invito al team",
"team_inviteGetData": "Ricezione di dati del gruppo in corso",
"team_inviteTitle": "Invito a un gruppo",
"burnAfterReading_linkBurnAfterReading": "Visualizza una sola volta, poi autodistruggi",
"oo_sheetMigration_loading": "È in corso l'aggiornamento del documento all'ultima versione, ci vorrà un minuto.",
"settings_cat_security": "Sicurezza e privacy",
@ -856,25 +856,25 @@
"admin_activePadsHint": "Numero di documenti attualmente aperti (visualizzato o in fase di modifica)",
"team_admins": "Amministratori/trici",
"team_cat_admin": "Amministrazione",
"team_kickedFromTeam": "{0} ti ha espulso/a dal team: <b>{1}</b>",
"team_infoContent": "Ogni team dispone di un proprio CryptDrive, spazio di archiviazione, chat ed elenco membri. I proprietari e le proprietarie hanno la facoltà di eliminare il team, gli amministratori e le amministratrici possono invitare o espellere i membri, mentre i membri possono decidere di lasciare il team.",
"team_kickedFromTeam": "{0} ti ha rimosso/a dal gruppo: <b>{1}</b>",
"team_infoContent": "Ogni gruppo dispone di un proprio CryptDrive (e relativo spazio di archiviazione), di una propria chat e del proprio elenco membri. I proprietari e le proprietarie hanno la facoltà di eliminare il gruppo, gli amministratori e le amministratrici possono invitare nuovi membri o rimuovere quelli esistenti, mentre i membri possono decidere di uscire dal gruppo.",
"team_owner": "Proprietari/e",
"team_leaveConfirm": "Se lasci questo team perderai l'accesso al suo CryptDrive, alla cronologia della chat ed agli altri contenuti. Sei sicuro/a?",
"team_leaveConfirm": "Se esci da questo gruppo perderai l'accesso al suo CryptDrive, alla cronologia della chat ed agli altri contenuti. Sei sicuro/a?",
"team_cat_drive": "Drive",
"team_declineInvitation": "{0} ha rifiutato la tua proposta di unirsi al team: <b>{1}</b>",
"team_invitedToTeam": "{0} ti ha invitato a unirsi suo team: <b>{1}</b>",
"team_pcsSelectHelp": "La creazione di un documento di tua proprietà nel drive del team ne attribuisce la proprietà al team stesso.",
"team_pickFriends": "Scegli i contatti da invitare a questo team",
"team_declineInvitation": "{0} ha rifiutato la tua proposta di entrare nel gruppo: <b>{1}</b>",
"team_invitedToTeam": "{0} ti ha invitato ad entrare nel suo gruppo: <b>{1}</b>",
"team_pcsSelectHelp": "La creazione di un documento di tua proprietà nel drive del gruppo ne attribuisce la proprietà al gruppo stesso.",
"team_pickFriends": "Scegli i contatti da invitare in questo gruppo",
"owner_removed": "{0} ha rimosso i tuoi diritti di proprietà per <b>{1}</b>",
"owner_request_declined": "{0} ha rifiutato la tua proposta di diventare proprietario/a di <b>{1}</b>",
"owner_add": "{0} propone tu sia proprietario/a del documento <b>{1}</b> Accetti?",
"owner_request_accepted": "{0} ha accettato la tua proposta di diventare proprietario/a di <b>{1}</b>",
"share_linkTeam": "Aggiungi al drive del team",
"share_linkTeam": "Aggiungi al drive del gruppo",
"owner_removedPending": "{0} ha rifiutato la tua proposta di essere co-proprietario/a di <b>{1}</b>",
"team_pcsSelectLabel": "Salva in",
"team_acceptInvitation": "{0} ha accettato la tua proposta di unirsi al team: <b>{1}</b>",
"team_infoLabel": "Informazioni sui team",
"team_rosterKick": "Espelli dal team",
"team_acceptInvitation": "{0} ha accettato la tua proposta di entrare nel gruppo: <b>{1}</b>",
"team_infoLabel": "Informazioni sui gruppi",
"team_rosterKick": "Rimuovi dal gruppo",
"team_rosterPromote": "Promuovi",
"team_inviteButton": "Invita membri",
"owner_request": "{0} propone tu sia proprietario/a di <b>{1}</b>",
@ -943,7 +943,7 @@
"support_cat_other": "Altro",
"support_cat_account": "Account",
"user_about": "Informazioni su CryptPad",
"support_languagesPreamble": "Il team di supporto parla le seguenti lingue:",
"support_languagesPreamble": "La squadra di assistenza parla le seguenti lingue:",
"slide_textCol": "Colore del testo",
"slide_backCol": "Colore di sfondo",
"toolbar_file": "File",
@ -961,9 +961,9 @@
"fm_restricted": "Non hai accesso",
"fm_emptyTrashOwned": "Il cestino contiene documenti di tua proprietà. Puoi <b>rimuoverli</b> solo dal tuo drive oppure <b>distruggerli</b> per tutti gli utenti e tutte le utenti.",
"oo_refresh": "Aggiorna",
"notification_folderSharedTeam": "{0} ha condiviso una cartella con il team {2}: <b>{1}</b>",
"notification_fileSharedTeam": "{0} ha condiviso un file con il team {2}: <b>{1}</b>",
"notification_padSharedTeam": "{0} ha condiviso un documento con il team {2}: <b>{1}</b>",
"notification_folderSharedTeam": "{0} ha condiviso una cartella con il gruppo {2}: <b>{1}</b>",
"notification_fileSharedTeam": "{0} ha condiviso un file con il gruppo {2}: <b>{1}</b>",
"notification_padSharedTeam": "{0} ha condiviso un documento con il gruppo {2}: <b>{1}</b>",
"support_cat_all": "Tutto",
"support_cat_bug": "Segnalazione di errori",
"support_cat_data": "Perdita di dati",
@ -1026,18 +1026,18 @@
"unableToDisplay": "Impossibile visualizzare il documento. Premi Esc per ricaricare la pagina. Se il problema persiste, contatta l'assistenza.",
"documentID": "Codice identificativo del documento",
"error_unhelpfulScriptError": "Errore di script: vedi la console del browser per i dettagli",
"loading_state_5": "Ricostruisci documento",
"loading_state_4": "Carica i team",
"loading_state_3": "Carica cartelle condivise",
"loading_state_2": "Aggiorna contenuto",
"loading_state_1": "Carica drive",
"loading_state_0": "Crea interfaccia",
"loading_state_5": "Ricostruzione del documento",
"loading_state_4": "Caricamento dei gruppi",
"loading_state_3": "Caricamento delle cartelle condivise",
"loading_state_2": "Aggiornamento del contenuto",
"loading_state_1": "Caricamento del drive",
"loading_state_0": "Creazione dell'interfaccia",
"fm_shareFolderPassword": "Proteggi questa cartella con una password (facoltativo)",
"access_destroyPad": "Distruggi questo documento o questa cartella in modo permanente",
"fm_deletedFolder": "Cartella eliminata",
"team_exportButton": "Scarica",
"team_exportHint": "Scarica tutti i documenti nel drive del tuo team. Ove possibile i documenti saranno scaricati in formati leggibili da altre applicazioni. Quando questo non sarà possibile, i documenti verranno scaricati in formati leggibili da CryptPad.",
"team_exportTitle": "Scarica il drive del team",
"team_exportHint": "Scarica tutti i documenti presenti nel drive del tuo gruppo. Ove possibile i documenti saranno scaricati in formati leggibili da altre applicazioni. Quando questo non sarà possibile, i documenti verranno scaricati in formati leggibili da CryptPad.",
"team_exportTitle": "Scarica il drive del gruppo",
"admin_cat_quota": "Spazio di archiviazione per gli/le utenti",
"admin_invalLimit": "Limite non valido",
"admin_setlimitTitle": "Applica un limite personalizzato",
@ -1049,9 +1049,9 @@
"admin_limit": "Limite attuale: {0}",
"admin_setlimitButton": "Imposta limite",
"admin_defaultlimitTitle": "Limite dello spazio di archiviazione (MB)",
"admin_defaultlimitHint": "Limite massimo dello spazio di archiviazione dei CryptDrive (utenti e team) se non vengono applicate regole personalizzate",
"admin_defaultlimitHint": "Limite massimo dello spazio di archiviazione dei CryptDrive (per utenti e gruppi) se non vengono applicate regole personalizzate",
"admin_registrationTitle": "Chiudi le registrazioni",
"admin_registrationHint": "Non consentire la registrazione di nuovi/e utenti",
"admin_registrationHint": "Chi visita l'istanza non ha l'autorizzazione per creare un account. Gli inviti possono essere creati dagli amministratori o dalle amministratrici.",
"snapshots_cantMake": "Impossibile creare l'istantanea. Sei disconnesso/a.",
"snapshots_notFound": "Questa istantanea non esiste più perché la cronologia del documento è stata eliminata.",
"snapshot_error_exists": "È già presente un'istantanea di questa versione",
@ -1158,7 +1158,7 @@
"settings_deleteSubscription": "Gestisci il mio abbonamento",
"calendar_weekNumber": "Settimana {0}",
"calendar_day": "Giorno",
"calendar_deleteTeamConfirm": "Sicuro/a di voler eliminare questo calendario dal team?",
"calendar_deleteTeamConfirm": "Sicuro/a di voler eliminare questo calendario dal gruppo?",
"calendar_deleteOwned": "Rimarrà visibile agli altri ed alle altre utenti con cui è stato condiviso.",
"calendar_loc": "Posizione",
"calendar_allDay": "Tutto il giorno",
@ -1329,19 +1329,19 @@
"calendar_settings": "Impostazioni del calendario",
"date": "Data",
"context_menu": "Azioni della cartella",
"team_nameTooLong": "Il nome del team è troppo lungo (massimo 50 caratteri)",
"team_nameAlreadySet": "Il nome del team è già {0}",
"team_nameTooLong": "Il nome del gruppo è troppo lungo (massimo 50 caratteri)",
"team_nameAlreadySet": "Il nome del gruppo è già {0}",
"dph_reason": "Motivo: {0}",
"dph_sf_destroyed": "La cartella condivisa <b>{0}</b> è stata distrutta da un proprietario o una proprietaria",
"dph_sf_destroyed_team": "La cartella condivisa <b>{0}</b> nel team drive <b>{1}</b> è stata distrutta da un proprietario o una proprietaria",
"dph_sf_destroyed_team": "La cartella condivisa <b>{0}</b> nel drive del gruppo <b>{1}</b> è stata distrutta da un proprietario o una proprietaria",
"dph_default": "Questo contenuto non è più disponibile",
"dph_account_moderated": "Questo account è stato sospeso dal team di moderazione",
"dph_account_moderated": "Questo account è stato sospeso dalla squadra di moderazione",
"dph_account_pw": "La password di questo account è stata modificata",
"dph_account_inactive": "Questo account è stato eliminato per inattività",
"dph_pad_inactive": "Questo documento è stato eliminato per inattività",
"dph_pad_moderated": "Questo documento è stato eliminato dal team di moderazione",
"dph_pad_moderated": "Questo documento è stato eliminato dalla squadra di moderazione",
"dph_tmp_destroyed": "Questo modello è stato distrutto da un proprietario o una proprietaria",
"dph_tmp_moderated": "Questo modello è stato eliminato dal team di moderazione",
"dph_tmp_moderated": "Questo modello è stato eliminato dalla squadra di moderazione",
"dph_tmp_moderated_account": "Questo modello è stato eliminato perché appartenente ad un account sospeso",
"access_passwordUsed": "Questa password è già stata usata per questo documento. Non può essere riutilizzata.",
"status": "Pagina di stato",
@ -1360,7 +1360,7 @@
"support_warning_bug": "Specifica in quale browser si verifica il problema e se sono installate estensioni. Fornisci il maggior numero possibile di dettagli sul problema e sui passaggi necessari per riprodurlo",
"ui_openDirectly": "Questa funzionalità non è disponibile quando CryptPad è incorporato in un altro sito. Vuoi aprire questo documento in una nuova scheda?",
"fivehundred_internalServerError": "Errore interno del server",
"support_cat_drives": "Drive o team",
"support_cat_drives": "Drive o gruppi",
"support_cat_document": "Documento",
"support_cat_abuse": "Segnalazione di abuso",
"error_embeddingDisabledSpecific": "L'incorporamento è disabilitato per questa applicazione di CryptPad.",
@ -1531,7 +1531,7 @@
"form_condition_v": "Scegli una risposta",
"support_warning_account": "Si noti che gli amministratori e le amministratrici non sono in grado di reimpostare le password. Se hai perso le credenziali del tuo account e sei ancora connesso/a, puoi <a>migrare i tuoi dati su un nuovo account</a>",
"ui_ms": "millisecondi",
"og_teamDrive": "Drive del team",
"og_teamDrive": "Drive del gruppo",
"og_default": "CryptPad: suite di collaborazione criptata end-to-end",
"calendar_rec_stop": "Interrompi la ripetizione",
"calendar_rec_freq_weekly": "settimane",
@ -1543,7 +1543,7 @@
"mfa_revoke_code": "Inserisci il codice di verifica",
"settings_otp_tuto": "Scansiona questo codice QR con la tua app di autenticazione e inserisci il codice di verifica per confermare.",
"oo_cantMigrate": "Questo foglio supera la dimensione massima di caricamento ed è troppo grande per essere migrato.",
"team_leaveOwner": "Prima uscire dal team devi abbandonare il ruolo di proprietario/a. Dato che i team devono avere almeno un proprietario o una proprietaria, se sei attualmente l'unico/a dovrai aggiungere un proprietario o una proprietaria prima di proseguire.",
"team_leaveOwner": "Prima uscire dal gruppo devi abbandonare il ruolo di proprietario/a. Dato che i gruppi devono avere almeno un proprietario o una proprietaria, se sei attualmente l'unico/a dovrai aggiungere un proprietario o una proprietaria prima di proseguire.",
"form_condorcetExtendedDisplay": "Numero di partite vinte da ogni candidato/a: ",
"recovery_mfa_error": "Errore sconosciuto. Ricarica e prova di nuovo.",
"mfa_revoke_button": "Conferma la disattivazione dell'autenticazione a due fattori",
@ -1593,7 +1593,7 @@
"admin_emailHint": "Imposta l'email di contatto per la tua istanza",
"admin_totpRecoveryHint": "Gli/le utenti possono copiare i dati di recupero nella pagina di ripristino dell'autenticazione a due fattori /recovery/ e inviarli via email agli amministratori e alle amministratrici dell'istanza. Incolla i dati di recupero qui sotto per disabilitare l'autenticazione a due fattori per un account",
"admin_totpRecoveryMethod": "Metodo di recupero dell'autenticazione a due fattori",
"admin_consentToContactHint": "La telemetria del server include l'email di contatto dell'amministratore/trice, in modo che il team di sviluppo ti possa informare di eventuali problemi gravi con il software o con la tua configurazione. L'email non sarà mai condivisa, venduta o utilizzata per scopi di marketing. Acconsenti ad essere contattato/a se desideri essere informato/a di problemi critici con il tuo server.",
"admin_consentToContactHint": "La telemetria del server include l'email di contatto dell'amministratore/trice, in modo che la squadra di sviluppo ti possa informare di eventuali problemi gravi con il software o con la tua configurazione. L'email non sarà mai condivisa, venduta o utilizzata per scopi di marketing. Acconsenti ad essere contattato/a se desideri essere informato/a di problemi critici con il tuo server.",
"admin_invitationCreate": "Crea link d'invito",
"admin_registrationSsoTitle": "Chiudi le registrazioni con SSO",
"admin_invitationTitle": "Link d'invito",
@ -1613,14 +1613,14 @@
"admin_supportInitGenerate": "Genera le chiavi dell'assistenza",
"admin_supportPrivButton": "Mostra chiave",
"admin_checkupButton": "Esegui la diagnostica",
"admin_removeDonateButtonHint": "Lo sviluppo di CryptPad è in parte finanziato da sovvenzioni e donazioni pubbliche. Pubblicizzare la nostra campagna di raccolta fondi sulla tua istanza aiuta il team di sviluppo a continuare il proprio lavoro. Se li ritieni inopportuni, puoi disattivare questi avvisi.",
"admin_removeDonateButtonHint": "Lo sviluppo di CryptPad è in parte finanziato da sovvenzioni e donazioni pubbliche. Pubblicizzare la nostra campagna di raccolta fondi sulla tua istanza aiuta la squadra di sviluppo a continuare il proprio lavoro. Se li ritieni inopportuni, puoi disattivare questi avvisi.",
"admin_removeDonateButtonLabel": "Non pubblicizzare le campagne di raccolta fondi",
"admin_blockDailyCheckTitle": "Telemetria del server",
"admin_blockDailyCheckHint": "Le istanze di CryptPad inviano un messaggio al server del team di sviluppo quando vengono installate e successivamente una volta al giorno. Ciò consente al team di sapere quali versioni del software sono in circolazione. Puoi disattivare la raccolta di questi dati qui sotto. Il contenuto dei messaggi può essere esaminato nel registro del server dell'applicazione.",
"admin_blockDailyCheckHint": "Le istanze di CryptPad inviano un messaggio al server della squadra di sviluppo quando vengono installate e successivamente una volta al giorno. Ciò consente alla squadra di sviluppo di sapere quali versioni del software sono in circolazione. Puoi disattivare la raccolta di questi dati qui sotto. Il contenuto dei messaggi può essere esaminato nel registro del server dell'applicazione.",
"admin_consentToContactLabel": "Acconsento",
"admin_blockDailyCheckLabel": "Disattiva la telemetria del server",
"admin_provideAggregateStatisticsTitle": "Aggregazione statistica",
"admin_provideAggregateStatisticsHint": "Puoi scegliere di fornire al team di sviluppo ulteriori metriche di utilizzo, come i numeri approssimativi di utenti registrati/e e di utenti giornalieri/e della tua istanza.",
"admin_provideAggregateStatisticsHint": "Puoi scegliere di fornire alla squadra di sviluppo ulteriori metriche di utilizzo, come i numeri approssimativi di utenti registrati/e e di utenti giornalieri/e della tua istanza.",
"admin_provideAggregateStatisticsLabel": "Fornisci statistiche aggregate",
"admin_instancePurposeTitle": "Obiettivo dell'istanza",
"admin_purpose_noanswer": "Preferisco non rispondere",
@ -1679,12 +1679,12 @@
"calendar_rec_warn_delall": "Questo evento non si ripeterà più. Il primo evento del {0} sarà mantenuto, tutti gli altri saranno rimossi.",
"calendar_rec_warn_updateall": "La regola per la ripetizione di questo evento è stata modificata. Il primo evento del {0} sarà mantenuto, tutti gli altri saranno sostituiti.",
"admin_forcemfaTitle": "Autenticazione a due fattori obbligatoria",
"admin_forcemfaHint": "A tutti gli utenti e tutte le utenti di questa istanza verrà chiesto di impostare l'autenticazione a due fattori per accedere al proprio account.",
"admin_forcemfaHint": "A tutti gli utenti e tutte le utenti di questa istanza verrà chiesto di impostare l'autenticazione a due fattori per accedere al proprio account. Gli/le utenti esistenti non potranno continuare a utilizzare il proprio account senza prima impostare un'applicazione TOTP.",
"admin_cat_security": "Sicurezza",
"admin_cat_customize": "Aspetto",
"admin_colorTitle": "Colore principale",
"admin_logoTitle": "Logo personalizzato",
"admin_supportAdd": "Aggiungi un contatto al team di assistenza",
"admin_supportAdd": "Aggiungi un contatto alla squadra di assistenza",
"admin_logoHint": "SVG, PNG o JPG, dimensione massima 200KB",
"admin_colorCurrent": "Colore principale attuale",
"admin_logoButton": "Carica nuovo logo",
@ -1697,18 +1697,18 @@
"admin_supportEnabled": "Il sistema di assistenza è abilitato.",
"support_cat_settings": "Impostazioni",
"admin_supportDisabled": "Il sistema di assistenza è disabilitato.",
"admin_supportMembers": "Team di assistenza",
"admin_supportMembers": "Squadra di assistenza",
"support_cat_search": "Cerca",
"support_privacyTitle": "Rispondi in modo anonimo",
"support_notificationsTitle": "Disattiva le notifiche",
"support_userKey": "Chiave pubblica dell'utente",
"support_invalChan": "Canale di notifica non valido",
"admin_supportTeamTitle": "Gestisci il team di assistenza",
"admin_supportTeamHint": "Aggiungi e rimuovi persone dal team di assistenza dell'istanza",
"admin_supportTeamTitle": "Gestisci la squadra di assistenza",
"admin_supportTeamHint": "Aggiungi e rimuovi persone dalla squadra di assistenza dell'istanza",
"support_pasteUserData": "Incolla qui i dati dell'utente",
"support_recordedContent": "Contenuto",
"support_answerAs": "Stai rispondendo come <b>{0}</b>",
"support_team": "Il team di assistenza",
"support_team": "La squadra di assistenza",
"support_movePending": "Sposta nell'archivio",
"admin_supportOpen": "Apri il servizio d'assistenza",
"moderationPage": "Servizio d'assistenza",
@ -1717,10 +1717,10 @@
"admin_cat_users": "Elenco utenti",
"admin_invitationCopy": "Copia link",
"admin_usersRemove": "Rimuovi",
"support_privacyHint": "Seleziona questa opzione per rispondere come \"Il team di assistenza\" invece che con il tuo nome utente",
"support_privacyHint": "Seleziona questa opzione per rispondere come \"La squadra di assistenza\" invece che con il tuo nome utente",
"earlyAccessBlocked": "Questa applicazione non è ancora disponibile su questa istanza",
"admin_invitationHint": "I link d'invito permettono di creare un account ciascuno, anche se le registrazioni sono chiuse. Il nome utente e l'email sono solo a scopo di identificazione. CryptPad non invierà il link d'invito (o qualsiasi altra comunicazione) via email. Copia il link qui sotto e invialo utilizzando un canale sicuro di tua scelta.",
"admin_supportRotateNotify": "Attenzione: le nuove chiavi sono state generate ma un errore imprevisto ha impedito al sistema di inviarle ai moderatori ed alle moderatrici. Si prega di rimuovere e aggiungere nuovamente tutti i membri del team di assistenza",
"admin_supportRotateNotify": "Attenzione: le nuove chiavi sono state generate ma un errore imprevisto ha impedito al sistema di inviarle ai moderatori ed alle moderatrici. Si prega di rimuovere e aggiungere nuovamente tutti i membri della squadra di assistenza",
"pad_tocHide": "Indice",
"admin_consentToContactTitle": "Acconsenti ad essere contattato/a",
"resources_learnWhy": "Per saperne di più sulle immagini bloccate",
@ -1734,5 +1734,12 @@
"support_recordedEmpty": "Nessuna scorciatoia",
"support_legacyTitle": "Visualizza i vecchi dati dell'assistenza",
"support_legacyDump": "Esporta tutte",
"support_insertRecorded": "Inserisci scorciatoia"
"support_insertRecorded": "Inserisci scorciatoia",
"pad_goToAnchor": "Vai all'ancora",
"onboarding_upload": "Seleziona un logo",
"onboarding_save_error": "Non è stato possibile salvare correttamente alcune opzioni. Visita il pannello di amministrazione per verificare i valori indicati.",
"admin_onboardingNameHint": "Scegli un titolo, una descrizione, un colore principale ed un logo (sono tutti facoltativi)",
"admin_onboardingNameTitle": "Benvenut* nella tua istanza di CryptPad",
"admin_onboardingNamePlaceholder": "Titolo dell'istanza",
"admin_onboardingDescPlaceholder": "Descrizione dell'istanza"
}

View file

@ -1138,7 +1138,7 @@
"notification_fileSharedTeam": "{0}がチーム({2})とファイル(<b>{1}</b>)を共有しました",
"notification_padSharedTeam": "{0}がチーム({2})とドキュメント(<b>{1}</b>)を共有しました",
"requestEdit_accepted": "{1}があなたにドキュメント(<b>{0}</b>)の編集権を付与しました",
"admin_registrationHint": "ユーザーの新規登録を許可しない",
"admin_registrationHint": "このインスタンスの訪問者にはアカウントの作成が許可されていません。管理人は招待を行うことができます。",
"oo_deletedVersion": "このバージョンは履歴に存在しません。",
"team_pickFriends": "チームに招待する連絡先を選択",
"notification_fileShared": "{0}があなたとファイルを共有しました: <b>{1}</b>",
@ -1692,7 +1692,7 @@
"calendar_rec_change": "繰り返しのイベントを異なるカレンダーに移動。この変更は、このイベントまたは全ての繰り返しのイベントに適用できます。",
"dph_pad_pw": "このドキュメントはパスワードにより保護されています",
"access_passwordUsed": "このパスワードは既にこのドキュメントに使用されています。再度利用することはできません。",
"admin_forcemfaHint": "このインスタンスの全てのユーザーに、ログイン用の二要素認証を設定するように要求します。",
"admin_forcemfaHint": "このインスタンスの全てのユーザーに、ログイン用の二要素認証を設定するように要求します。なお、既存のユーザーが使用を継続するには、二要素認証のアプリケーションを設定する必要があります。",
"admin_invitationHint": "招待リンクは、登録が締め切られている場合でもアカウントを1つ作成します。ユーザー名とメールアドレスは、ユーザーの特定用にのみ使用します。CryptPadは、招待リンクその他を電子メールで送信することはありません。リンクをコピーし、何か安全な方法でリンクを送信してください。",
"admin_usersHint": "このインスタンスの既知のアカウントの一覧。以下を選択してアカウントを自動的に追加するか、フォームから手動で情報を入力してください。",
"admin_diskUsageWarning": "注意して使用してください!このインスタンスに保存されているデータのサイズ次第では、このレポートを作成すると、サーバーで利用可能な全てのメモリー量を使用し、クラッシュする可能性があります。",
@ -1754,5 +1754,22 @@
"admin_supportInit": "このインスタンスのヘルプデスクを初期化",
"admin_supportRotateNotify": "警告:新しい鍵が作成されましたが、不明なエラーのため、モデレーターに送信できませんでした。サポートチームの全メンバーを削除し、改めて追加してください",
"admin_supportTeamHint": "インスタンスのサポートチームにメンバーを追加したり、サポートチームからメンバーを削除したりできます",
"admin_colorHint": "あなたのCryptPadインスタンスのアクセントの色を変更できます。ライトテーマとダークテーマの両方で、テキストとボタンが十分なコントラストを備えており、可読性があることを確認してください。"
"admin_colorHint": "あなたのCryptPadインスタンスのアクセントの色を変更できます。ライトテーマとダークテーマの両方で、テキストとボタンが十分なコントラストを備えており、可読性があることを確認してください。",
"support_recordedHint": "共通のテキストをショートカットとして保存すると、クリックでサポート用メッセージに挿入することができます。",
"install_token": "インストール用のトークン",
"install_header": "インストール",
"admin_appSelection": "アプリケーションの設定",
"install_launch": "インスタンスのセットアップ",
"admin_appsTitle": "インスタンスのアプリケーション",
"admin_appsHint": "このインスタンスで有効にするアプリケーションを選択してください。",
"admin_cat_apps": "アプリケーション",
"onboarding_upload": "ロゴを選択してください",
"onboarding_save_error": "いくつかの設定を適切に保存できませんでした。管理用パネルから値を確認してください。",
"admin_onboardingNameHint": "タイトル、説明文、アクセントの色、ロゴを選択してください(全て任意です)",
"admin_onboardingNameTitle": "あなたのCryptPadのインスタンスにようこそ",
"support_legacyHint": "旧式のサポートシステムのチケットを表示した後、新しいサポートシステムで改めてチケットを作成します。",
"admin_onboardingOptionsTitle": "インスタンスのオプション",
"admin_onboardingOptionsHint": "インスタンスに適切な設定を選択してください。</br>これらの設定は、後から管理者パネルで変更できます。",
"admin_onboardingNamePlaceholder": "インスタンスのタイトル",
"admin_onboardingDescPlaceholder": "インスタントの説明文"
}

View file

@ -1004,7 +1004,7 @@
"snapshot_error_exists": "There is already a snapshot of this version",
"snapshots_notFound": "This snapshot no longer exists because the history of the document has been deleted.",
"snapshots_cantMake": "The snapshot could not be created. You are disconnected.",
"admin_registrationHint": "Do not allow any new users to register",
"admin_registrationHint": "Visitors to the instance are not able to create accounts. Invitations can be created by administrators.",
"admin_registrationTitle": "Close registration",
"admin_defaultlimitHint": "Maximum storage limit for CryptDrives (users and teams) when no custom rule is applied",
"admin_defaultlimitTitle": "Storage limit (MB)",
@ -1680,7 +1680,7 @@
"kanban_showTags": "See all tags",
"kanban_hideTags": "See less tags",
"admin_forcemfaTitle": "Mandatory Two-Factor Authentication",
"admin_forcemfaHint": "All users on this instance will be asked to set up two-factor authentication to log in to their account.",
"admin_forcemfaHint": "All users on this instance will be asked to set up two-factor authentication to log in to their account. Note that existing users will not be able to keep using their account without setting up a TOTP application.",
"loading_mfa_required": "Two-factor authentication is required on this instance. Please update your account using an authenticator app and the form below.",
"admin_cat_users": "User directory",
"admin_registrationSsoTitle": "Close SSO registration",
@ -1763,5 +1763,22 @@
"support_copyUserData": "Copy user data",
"support_insertRecorded": "Insert snippet",
"admin_supportOpen": "Open help-desk",
"support_userNotification": "New support ticket or response: {0}"
"support_userNotification": "New support ticket or response: {0}",
"install_instance": "Create the first admin account, then proceed to customize this instance",
"install_token": "Installation token",
"install_header": "Installation",
"admin_appSelection": "App configuration",
"install_launch": "Instance setup",
"install_notes": "<ul class=\"cp-notes-list\"><li>Create your first administrator account on this page. Administrators manage instance settings including storage quotas, and have access to moderation tools.</li><li>Your password is the secret key that encrypts all of your documents and administrator privileges on this instance. <span class=\"red\">If you lose it there is no way we can recover your data.</span></li><li>If you are using a shared computer, <span class=\"red\">remember to log out</span> when you are done. Only closing the browser window leaves your account exposed. </li></ul>",
"admin_appsTitle": "Instance applications",
"onboarding_save_error": "Some options could not be saved properly. Please visit the administration panel to check the values.",
"admin_appsHint": "Choose which apps to enable on this instance.",
"admin_cat_apps": "Applications",
"onboarding_upload": "Select logo",
"admin_onboardingNameTitle": "Welcome to your CryptPad instance",
"admin_onboardingNameHint": "Please choose a title, description, accent color and logo (all are optional)",
"admin_onboardingOptionsTitle": "Instance options",
"admin_onboardingOptionsHint": "Please select the appropriate option for your instance.<br>These settings can be changed later in the admin panel.",
"admin_onboardingNamePlaceholder": "Instance title",
"admin_onboardingDescPlaceholder": "Instance description text"
}

View file

@ -1,5 +1,116 @@
{
"type": {
"drive": "CryptDrive"
}
"drive": "CryptDrive",
"slide": "마크다운(MD) 슬라이드",
"file": "파일",
"media": "미디어",
"todo": "할 일",
"form": "양식",
"teams": "협업",
"doc": "문서",
"presentation": "발표자료",
"diagram": "다이어그램",
"kanban": "칸반",
"poll": "투표",
"whiteboard": "화이트보드",
"contacts": "연락처",
"sheet": "시트"
},
"formattedMB": "{0} MB",
"propertiesButtonTitle": "문서 속성 받기",
"onLogout": "로그아웃 하셨습니다, {0}여기를 누르세요{1} 로그인 하기<br> 아니면 'ESC' 버튼을 눌러 읽기전용 모드로 문서를 여십시오.",
"padNotPinnedVariable": "해당문서는 {4}일 후 비활성 파기됩니다, {0}로그인{1} or {2}등록{3} 하여 권한을 얻기.",
"expiredError": "해당문서는 파기기한이 도래하여 더 이상 사용이 불가능 합니다.",
"deletedError": "해당 문서는 이미 삭제되어 활용이 불가능 합니다.",
"inactiveError": "해당 문서는 비활성 파기되었습니다. 'ESC' 버튼을 눌러 새 문서를 작성하세요.",
"invalidHashError": "요청한 문서의 URL이 유효하지 않습니다.",
"errorCopy": " 'ESC'버튼을 누르면 읽기전용모드로 계속 사용 가능합니다.",
"errorRedirectToHome": "'ESC'버튼을 눌러 당신의 CryptDrive로 되돌아가십시오.",
"loading": "불러오는 중...",
"error": "오류",
"saved": "저장 됨",
"deleted": "삭제됨",
"deletedFromServer": "문서 파괴됨",
"mustLogin": "해당 페이지에 접근하려면 로그인 하셔야 합니다",
"realtime_unrecoverableError": "회생불가의 오류 발생. 'OK'를 눌러 다시 불러오세요.",
"disconnected": "연결 해제",
"synchronizing": "동기화 중",
"reconnecting": "재연결 중",
"typing": "편집",
"initializing": "초기화 중...",
"forgotten": "쓰레기통으로 이동",
"errorState": "치명적 오류: {0}",
"readonly": "읽기 전용",
"anonymous": "손님",
"users": "사용자",
"viewer": "관찰자",
"viewers": "관찰자들",
"editor": "편집기",
"userlist_offline": "현재 오프라인상태라 사용자목록을 이용 불가능 합니다.",
"language": "언어",
"upgrade": "승급",
"upgradeAccount": "계정 승급",
"GB": "GB",
"KB": "kB",
"formattedGB": "{0} GB",
"pinLimitReached": "저장소 용량이 가득 찼습니다",
"pinLimitReachedAlertNoAccounts": "저장소 용량이 가득찼습니다",
"pinLimitNotPinned": "저장소 용량이 가득 찼습니다. <br>CryptDrive에 새로운 문서를 저장 할 수 없습니다.",
"pinLimitDrive": "저장소 용량이 가득 찼습니다. CryptDrive에 새로운 문서를 생성 할 수 없습니다.",
"importButton": "불러오기",
"importButtonTitle": "로컬파일을 불러오기",
"exportButton": "내보내기",
"exportButtonTitle": "로컬 파일로 내보내기",
"exportPrompt": "선호하는 파일명은?",
"user_rename": "표시명 변경",
"user_displayName": "표시명",
"user_accountName": "계정명",
"saveTitle": "제목저장 (enter)",
"forgetButton": "삭제",
"movedToTrash": "파일을 쓰레기통에 있습니다.<br><a>내 저장소에 접속하세요</a>",
"shareButton": "공유하기",
"shareSuccess": "링크를 클립보드에 저장",
"userListButton": "사용자 목록",
"chatButton": "말하기",
"userAccountButton": "사용자 메뉴",
"newButton": "새",
"newButtonTitle": "새 문서 생성",
"uploadButton": "파일들 올리기",
"uploadFolderButton": "폴더를 올리기",
"saveTemplateButton": "양식으로 저장",
"saveTemplatePrompt": "양식의 제목 고르기",
"templateSaved": "양식 저장됨!",
"selectTemplate": "양식으로 저장하거나 ESC 누르기",
"useTemplate": "양식으로 시작하겠습니까?",
"useTemplateCancel": "새로운 시작 (ESC)",
"template_import": "양식 불러오기",
"template_empty": "가용 양식이 없어",
"previewButtonTitle": "마크다운(MD) 미리보기 표시 or 숨기기",
"presentButtonTitle": "발표모드 진입",
"colorButtonTitle": "발표모드 글 색상 변경",
"propertiesButton": "속성들",
"printText": "출력",
"printButton": "출력 (enter)",
"printButtonTitle2": "문서 출력 하거나 PDF파일로 변환하기",
"printOptions": "층 설정",
"printSlideNumber": "판 번호 표시",
"printDate": "날짜 표시",
"printTitle": "문서 제목 표시",
"formattedKB": "{0}kB",
"common_connectionLost": "<b>서버 연결 실패</b><br>연결이 재개되기 전까지 읽기전용 모드로 사용됩니다.",
"typeError": "해당 어플리캐이션에서 이 문서가 호환되지 않습니다",
"padNotPinned": "해당문서는 3개월 이상 비활성되어 파기되었습니다, {0}로그인{1} or {2}등록{3} 하여 권한을 얻기.",
"anonymousStoreDisabled": "CryptPad의 관리자가 '게스트'에게 저장공간 사용을 금지하였습니다. 로그인하여 당신의 CryptDrive에 접속하세요.",
"chainpadError": "중요한 판올림 오류 발생. 해당 페이지는 읽기전용 모드로 전환됩니다. <br>'ESC'버튼을 눌러 계속 보거나, 편집을 다시 시도하십시오.",
"newVersionError": "Crytpad의 새로운 버전이 사용 가능합니다.<br><a href='#'>새버전으로 다시 불러오기</a>, <b>또는 'ESC'를 눌러 오프라인 모드로 접근하기</b>.",
"disabledApp": "해당 어플리캐이션은 비활성화 되었습니다. 이 CryptPad의 관리자에게 연락하여 추가 정보를 얻으세요.",
"storageStatus": "Storage:<br><b>{0}</b> 사용 중 <b>{1}</b>",
"MB": "MB",
"pinLimitReachedAlert": "저장소 용량이 가득 찼습니다. CryptDrive에 새로운 문서를 저장 할 수 없습니다.<br>CryptDrive의 문서를 지우거나 <a>프리미엄을 구독하여</a> 당신의 가용용량을 늘리세요.",
"clickToEdit": "눌러서 수정하기",
"forgetPrompt": "OK를 누르면 삭제됩니다. 확실한가요?",
"uploadButtonTitle": "당신의 CryptDrive에 새로운 파일을 올리기",
"useTemplateOK": "양식을 고르세요 (Enter)",
"backgroundButtonTitle": "발표 배경판 색상 변경",
"printCSS": "Custom style rules (CSS):"
}

View file

@ -1130,7 +1130,7 @@
"admin_getlimitsTitle": "Индивидуальные лимиты",
"admin_getlimitsHint": "Список все индивидуальных лимитов хранилища, применяемых в Вашем экземпляре.",
"admin_defaultlimitHint": "Максимальный лимит хранилища для CryptDrives (пользователи и команды), когда не задано индивидуального правила",
"admin_registrationHint": "Не позволять новым пользователям регистрироваться",
"admin_registrationHint": "Посетители экземпляра не могут создавать учетные записи. Администраторы могут создавать приглашения на регистрацию.",
"oo_version_latest": "Последняя",
"history_restoreDrivePrompt": "Вы уверены, что хотите заменить текущую версию CryptDrive на отображаемую версию?",
"history_restoreDriveTitle": "Восстановить выбранную версию CryptDrive",
@ -1622,7 +1622,7 @@
"ssoauth_form_hint_register": "Добавьте пароль CryptPad для дополнительной безопасности или оставьте пустым и продолжайте. Если вы не добавите пароль, ключи, защищающие ваши данные, будут доступны администраторам экземпляра.",
"settings_removeOwnedHint": "Все документы, в которых Вы являетесь единственным владельцем, будут безвозвратно уничтожены",
"admin_channelPlaceholder": "Заглушка на месте уничтоженного документа",
"admin_forcemfaHint": "Всем пользователям этого экземпляра будет предложено настроить двухфакторную аутентификацию для входа в свою учетную запись.",
"admin_forcemfaHint": "Всем пользователям этого экземпляра будет предложено настроить двухфакторную аутентификацию для входа в свою учетную запись. Обратите внимание, что существующие пользователи не смогут продолжать использовать свою учетную запись без настройки приложения TOTP.",
"admin_totpDisable": "Отключение 2FA для этой учетной записи",
"loading_enter_otp": "Эта учетная запись защищена двухфакторной аутентификацией. Пожалуйста, введите свой проверочный код",
"calendar_rec_change": "Перенос повторяющегося события в другой календарь. Вы можете применить это изменение только к этому событию или ко всем повторам этого события.",
@ -1763,5 +1763,22 @@
"admin_supportSetupHint": "Создайте или обновите ключи поддержки.",
"admin_supportMembers": "Команда Поддержки",
"support_privacyHint": "Установите этот флажок, чтобы отвечать как «Команда Поддержки», а не от своего имени пользователя",
"support_openTicketHint": "Копирует данные пользователя-получателя со страницы его профиля или существующего запроса в службу поддержки. Они получат уведомление CryptPad об этом сообщении."
"support_openTicketHint": "Копирует данные пользователя-получателя со страницы его профиля или существующего запроса в службу поддержки. Они получат уведомление CryptPad об этом сообщении.",
"install_token": "Токен установки",
"install_header": "Установка",
"admin_appSelection": "Конфигурация приложений",
"install_launch": "Настройка экземпляра",
"admin_appsTitle": "Приложения на данном экземпляре",
"admin_appsHint": "Выберите, какие приложения включить на этом экземпляре.",
"admin_cat_apps": "Приложения",
"onboarding_upload": "Выберите логотип",
"admin_onboardingNameTitle": "Добро пожаловать в Ваш экземпляр CryptPad",
"install_notes": "<ul class=\"cp-notes-list\"><li>Создайте свою первую учетную запись администратора на этой странице. Администраторы управляют настройками экземпляра, включая квоты хранилища, и имеют доступ к инструментам модерации.</li><li>Ваш пароль — это секретный ключ, который шифрует все Ваши документы и права администратора в этом экземпляре. <span class=\"red\">Если Вы потеряете его, мы не сможем восстановить Ваши данные.</span></li><li>Если Вы используете общий компьютер, <span class=\"red\">не забывайте выходить из учётной записи Cryptpad </span>, когда заканчиваете работу. Только лишь закрывая окно браузера Вы оставляете Вашу учетную запись открытой. </li></ul>",
"onboarding_save_error": "Не удалось сохранить некоторые параметры должным образом. Пожалуйста, посетите панель администрирования, чтобы проверить значения.",
"admin_onboardingOptionsTitle": "Параметры экземпляра",
"admin_onboardingNameHint": "Пожалуйста, выберите название, описание, цветовой акцент и логотип (всё по желанию)",
"admin_onboardingOptionsHint": "Пожалуйста, выберите подходящий вариант для Вашего экземпляра.<br>Эти настройки можно изменить позже в панели администратора.",
"admin_onboardingNamePlaceholder": "Заголовок экземпляра",
"install_instance": "Создайте первую учетную запись администратора, а затем приступайте к настройке этого экземпляра",
"admin_onboardingDescPlaceholder": "Текст описания экземпляра"
}

View file

@ -8,12 +8,16 @@
"file": "Dosya",
"whiteboard": "Beyaz Tahta",
"drive": "CryptSürücü",
"slide": "Sunum",
"slide": "Markdown Sunumları",
"poll": "Anket",
"code": "Kod",
"pad": "Zengin metin biçimi",
"doc": "Doküman",
"presentation": "Sunum"
"presentation": "Sunum",
"diagram": "Diyagram",
"sheet": "Sheet",
"kanban": "Kanban",
"form": "Form"
},
"main_catch_phrase": "Ekip iş birliği sistemi, <br>şifreli ve açık kaynak",
"main_title": "CryptPad: Tamamen Gizli, İşbirliğine Dayalı Gerçek Zamanlı Düzenleme",

View file

@ -104,7 +104,7 @@
"contacts_confirmRemove": "Точно вилучити <em>{0}</em> із контактів?",
"contacts_remove": "Вилучити контакт",
"contacts_send": "Надіслати",
"contacts_request": "<em>{0}</em> пропонує вам контакт. <b>Прийняти</b>?",
"contacts_request": "<em>{0}</em> хоче додати вас до списку контактів. <b>Схвалити</b>?",
"contacts_rejected": "Запрошення на контакт відхилено",
"contacts_added": "Запрошення на контакт прийнято.",
"contacts_title": "Контакти",
@ -308,7 +308,7 @@
"settings_autostoreNo": "Запитувати",
"settings_autostoreYes": "Автоматично",
"settings_autostoreHint": "<b>Автоматично</b> Всі відкриті документи зберігатимуться до вашого CryptDrive-каталогу.<br><b>Запитувати</b> Якщо ваш CryptDrive-каталог ще не містить документа, вам буде запропоновано його туди зберегти.<br><b>Вручну</b> Жодних документів не буде автоматично збережено до CryptDrive-каталогу. Пропозицію їх зберегти буде сховано.",
"settings_autostoreTitle": "Зберігати до CryptDrive-каталогу",
"settings_autostoreTitle": "Зберігання документів у CryptDrive",
"settings_importDone": "Імпорт завершено",
"settings_importConfirm": "Точно імпортувати нещодавні документи цього переглядача до CryptDrive-каталогу вашого облікового запису?",
"settings_import": "Імпорт",
@ -376,7 +376,7 @@
"login_unhandledError": "Виникла неочікувана помилка :(",
"login_invalPass": "Пароль обов'язковий",
"login_invalUser": "Псевдонім обов'язковий",
"login_noSuchUser": "Хибний псевдонім чи пароль. Повторіть спробу чи зареєструйтесь",
"login_noSuchUser": "Хибний псевдонім чи пароль",
"login_hashing": "Триває хешування паролю, просимо зачекати.",
"deleted": "Видалено",
"saved": "Збережено",
@ -388,7 +388,7 @@
"invalidHashError": "Ви спробували переглянути документ за хибною URL-адресою.",
"chainpadError": "При оновленні вашого файлу виникла критична помилка. Сторінку переведено до режиму читання, щоб ви не втратили своєї роботи.<br>Натисніть Esc, щоб переглянути документ, або перезавантажте, щоб продовжити редагування.",
"inactiveError": "Документ видалено через бездіяльність. Натисніть Esc, щоб створити новий.",
"expiredError": "Документ стерто через бездіяльність.",
"expiredError": "Цей документ досягнув терміну знищення і більше не є доступним.",
"deletedError": "Документ видалено.",
"anonymousStoreDisabled": "Адміністрація цього сервера CryptPad вимкнула гостьовий доступ до файлів. Увійдіть, щоб доступитися свого CryptDrive-каталогу.",
"padNotPinnedVariable": "Документ буде стерто через {4} дні бездіяльності. {0}Ввійдіть{1} або {2}зареєструйтесь{3}, щоб зберігати його довше.",
@ -412,7 +412,8 @@
"kanban": "Канбан",
"poll": "Опитування",
"code": "Код",
"pad": "Гіпертекст"
"pad": "Гіпертекст",
"diagram": "Діаграма"
},
"main_title": "CryptPad: спільне редагування наживо — це просто",
"upload_modal_owner": "Власний файл",
@ -518,7 +519,7 @@
"upload_cancelled": "Скасовано",
"upload_pending": "Очікування",
"upload_choose": "Обрати файл",
"upload_tooLargeBrief": "Файл перевищує межу: {0}МБ",
"upload_tooLargeBrief": "Файл перевищує обмеження {0}MB для цього диска",
"upload_tooLarge": "Файл важить більше, ніж дозволено вивантажувати вашим обліковим записом.",
"upload_notEnoughSpaceBrief": "Бракує простору",
"upload_notEnoughSpace": "Простору в CryptDrive-каталозі недостатньо для цього файлу.",
@ -758,7 +759,7 @@
"settings_colorthemeTitle": "Палітра",
"settings_cat_style": "Оформлення",
"settings_cat_kanban": "Канбан",
"settings_cat_security": "Конфіденційність",
"settings_cat_security": "Безпека та конфіденційність",
"slide_textCol": "Колір тексту",
"slide_backCol": "Колір тла",
"infobar_versionHash": "Ви переглядаєте стару версію цього документа ({0}).",
@ -777,7 +778,7 @@
"docs_link": "Документація",
"creation_helperText": "Відкрити документацію",
"creation_new": "Створити {0}",
"creation_expiresIn": "Чинно ще",
"creation_expiresIn": "Знищити в",
"register_registrationIsClosed": "Реєстрацію закрито.",
"admin_supportInitHelp": "Для вашого сервера ще не налаштовано скриньки підтримки. Якщо бажаєте отримувати на скриньку підтримки листи від користувачок і користувачів, попрохайте адміністрацію сервера запустити скрипт «./scripts/generate-admin-keys.js», додати відкритий ключ у файл «config.js» і надіслати вам закритий ключ.",
"admin_cat_support": "Підтримка",
@ -820,11 +821,11 @@
"contact_devHint": "Щодо бажаних функцій, удосконалення інтерфейсу чи просто подяки.",
"contact_dev": "Сконтактуйте з командою розробки",
"contact_adminHint": "Щодо будь-яких проблем з обліковим записом, просторовим обмеженням чи доступністю служби.\n",
"contact_admin": "Зв'язатися з адміністрацією: {0}",
"contact_admin": "Зверніться до адміністраторів для: {0}",
"footer_donate": "Пожертвувати",
"admin_flushCacheDone": "Кеш успішно стерто",
"admin_flushCacheButton": "Стерти кеш",
"admin_flushCacheHint": "Примусити користувачок і користувачів завантажити найновіші клієнтські ресурси (лише якщо ваш сервер — у режимі «fresh»)",
"admin_flushCacheHint": "Змушує всіх користувачів завантажувати найновіші ресурси після зміни налаштувань або конфігурації. Уникає перезавантаження сервера, але змушує кожного активного користувача скинути з'єднання, будь ласка, використовуйте економно.",
"admin_flushCacheTitle": "Стерти HTTP-кеш",
"admin_updateLimitDone": "Оновлення успішно завершено",
"admin_updateLimitButton": "Оновити квоти",
@ -845,7 +846,7 @@
"survey": "Опитування CryptPad",
"crowdfunding_popup_no": "Поки ні",
"crowdfunding_popup_text": "<h3>Нам потрібна ваша допомога!</h3> Щоб активна розробка CryptPad тривала, підтримайте проєкт через сторінку OpenCollective, де ви можете переглянути <b>план</b> і <b>фінансові цілі</b>.",
"crowdfunding_button2": "Допомогти CryptPad",
"crowdfunding_button2": "Пожертвувати",
"crowdfunding_button": "Підтримати CryptPad",
"autostore_notAvailable": "Збережіть цей документ до свого CryptDrive-каталогу, щоб змогти використати цю функцію.",
"autostore_forceSave": "Зберегти файл до CryptDrive-каталогу",
@ -891,7 +892,7 @@
"password_info": "Документ, який ви намагаєтесь відкрити, було стерто чи захищено новим паролем. Введіть чинний пароль, щоб доступитися вмісту.",
"creation_newPadModalDescription": "Натисніть застосунок, яким слід створити документ. Або оберіть його клавішею <b>Tab</b> і підтвердьте клавішею <b>Enter</b>.",
"creation_passwordValue": "Пароль",
"creation_expiration": ійсний до",
"creation_expiration": ата знищення",
"creation_noOwner": "Нічий",
"creation_owners": "Власність",
"creation_create": "Створити",
@ -977,7 +978,7 @@
"team_cat_back": "Назад до команд",
"team_cat_drive": "Каталог",
"team_cat_chat": "Бесіда",
"team_avatarHint": "Максимум 500 кБ (png, jpeg, gif)",
"team_avatarHint": "Максимальний розмір 500 кБ (png, jpg, jpeg, gif)",
"team_avatarTitle": "Аватар команди",
"team_cat_admin": "Адміністрація",
"team_deleteButton": "Видалити",
@ -1007,8 +1008,8 @@
"notifications_cat_all": "Всі",
"notificationsPage": "Сповіщення",
"openNotificationsApp": "Відкрити панель сповіщень",
"team_demoteMeConfirm": "Точно позбутися своїх повноважень? Цього неможливо буде скасувати.",
"owner_removeMeConfirm": "Точно позбутися свого права власності? Цього неможливо буде скасувати.",
"team_demoteMeConfirm": "Відмовитися від своїх повноважень. Ви не зможете скасувати цю дію. Впевнені?",
"owner_removeMeConfirm": "Відмовитися від своїх прав власності. Ви не зможете скасувати цю дію. Впевнені?",
"owner_removePendingText": "Очікування",
"owner_removeText": "Власність",
"access_offline": "Зараз ви поза мережею. Керування доступом недоступне.",
@ -1157,5 +1158,381 @@
"admin_registrationTitle": "Закрити реєстрацію",
"ui_restore": "Відновити",
"ui_archive": "Архівувати",
"admin_documentType": "Тип"
"admin_documentType": "Тип",
"mdToolbar_tutorial": "https://www.markdowntutorial.com/",
"admin_supportAddError": "Неправильний приватний ключ",
"support_disabledTitle": "Підтримку не ввімкнено",
"support_disabledHint": "Цей інстанс CryptPad ще не налаштований на використання форми підтримки.",
"support_cat_new": "Новий тікет",
"support_formTitle": "Новий тікет",
"support_formButton": "Надіслати",
"support_formTitleError": "Помилка: заголовок порожній",
"support_formContentError": "Помилка: вміст порожній",
"support_formMessage": "Введіть своє повідомлення…",
"admin_supportAddKey": "Додати приватний ключ",
"admin_supportListHint": "Ось список тікетів, надісланих користувачами на поштову скриньку підтримки. Всі адміністратори можуть бачити повідомлення та відповіді на них. Закритий тікет не може бути відкритий повторно. Ви можете лише видалити (приховати) закриті тікети, при цьому видалені тікети залишаються видимими для інших адміністраторів.",
"support_formHint": "Використовуйте цю форму для безпечного зв'язку з адміністраторами щодо проблем і питань.<br>Зверніть увагу, що деякі проблеми/питання вже можуть бути висвітлені в<a>CryptPad User Guide</a>. Будь ласка, не створюйте новий тикет, якщо у вас уже є відкритий тикет щодо тієї самої проблеми. Натомість, відповідайте на своє оригінальне повідомлення з будь-якою додатковою інформацією.",
"support_cat_tickets": "Наявні квитки",
"support_listTitle": "Тікети підтримки",
"support_listHint": "Ось список тикетів, надісланих адміністраторам, та їхні відповіді. Закритий тікет не може бути відкритий повторно, але ви можете створити новий. Ви можете приховати закриті тікети.",
"support_answer": "Відповісти",
"support_close": "Закрити тікет",
"support_remove": "Видалити тікет",
"support_showData": "Показати/приховати користувацьку інформацію",
"support_from": "<b>Від:</b> {0}",
"support_closed": "Цей тікет закрито",
"fc_noAction": "Дії недоступні",
"requestEdit_viewPad": "Відкрити документ у новій вкладці",
"later": "Вирішити пізніше",
"requestEdit_request": "{1} хоче відредагувати документ <b>{0}</b>",
"requestEdit_accepted": "{1} надав вам права на редагування документа<b>{0}</b>",
"requestEdit_sent": "Запит надіслано",
"properties_unknownUser": "{0} невідомий(і) користувач(и)",
"owner_unknownUser": "невідомо",
"owner_addConfirm": "Співвласники зможуть змінювати контент і видалити вас як власника. Ви впевнені?",
"owner_add": "{0} хоче, щоб ви стали власником документа <b>{1}</b>. Ви згодні?",
"owner_request_accepted": "{0} прийняв вашу пропозицію стати власником <b>{1}</b>",
"owner_removed": "{0} позбавив вас права власності на <b>{1}</b>",
"owner_removedPending": "{0} скасував вашу пропозицію щодо володіння для <b>{1}</b>",
"team_pcsSelectLabel": "Зберігати в",
"team_invitedToTeam": "{0}запросив вас приєднатись у його команду: <b>{1}</b>",
"team_kickedFromTeam": "{0} вигнав вас з команди: <b>{1}</b>",
"team_acceptInvitation": "{0} прийняв вашу пропозицію приєднатися до команди: <b>{1}</b>",
"team_rosterDemote": "Розжалувати",
"team_rosterKick": "Вигнати з команди",
"team_inviteButton": "Запросити учасників",
"team_nameTitle": "Назва команди",
"team_nameHint": "Встановити імʼя команді",
"team_maxTeams": "Кожен обліковий запис користувача може бути членом лише {0} команд.",
"owner_team_add": "{0} хоче, щоб ви стали власником команди <b>{1}</b>. Ви згодні?",
"team_rosterPromoteOwner": "Запропонувати право власності",
"team_kickConfirm": "{0} дізнаються, що ви видалили їх з команди. Ви впевнені?",
"sent": "Повідомлення надіслано",
"team_pending": "Запрошено",
"team_deleteTitle": "Видалення команди",
"team_pendingOwner": "(на розгляді)",
"team_pendingOwnerTitle": "Цей адміністратор ще не прийняв пропозицію власності.",
"drive_sfPasswordError": "Хибний пароль",
"password_error_seed": "Документ не знайдено!<br>Цю помилку може спричинити дві причини: або було додано/змінено пароль, або документ було видалено з сервера.",
"properties_confirmNewFile": "Ви впевнені? Додавання пароля змінить URL-адресу цього файлу. Користувачі без пароля втратять доступ до цього файлу.",
"properties_passwordSuccessFile": "Пароль успішно змінено.",
"teams_table": "Ролі",
"teams_table_generic": "Ролі та права",
"teams_table_generic_view": "Перегляд: доступ до папок і документів (тільки для читання).",
"teams_table_generic_edit": "Редагувати: створювати, змінювати та видаляти папки і документи.",
"teams_table_generic_admin": "Керувати учасниками: запрошувати та відкликати учасників, змінювати ролі учасників аж до Адміністратора.",
"teams_table_specific": "Виняток",
"teams_table_admins": "Керувати учасниками",
"teams_table_owners": "Керувати командою",
"teams_table_role": "Роль",
"pad_wordCount": "Слів: {0}",
"share_contactPasswordAlert": "Цей елемент захищено паролем. Оскільки ви ділитеся ним з контактом CryptPad, одержувачу не потрібно буде вводити пароль.",
"share_embedPasswordAlert": "Цей елемент захищено паролем. Коли ви вбудуєте цей документ, глядачам буде запропоновано ввести пароль.",
"passwordFaqLink": "Прочитати більше щодо паролів",
"contacts_mute": "Приглушити",
"contacts_unmute": "Увімкнути",
"team_inviteLinkTitle": "Створити персоналізоване запрошення для цієї команди",
"team_inviteLinkTempName": "Тимчасове ім'я (видно у списку очікуваних запрошень)",
"team_inviteLinkNote": "Додати персональне повідомлення",
"team_inviteLinkNoteMsg": "Це повідомлення буде показано до того, як одержувач вирішить, чи приєднатися до цієї команди.",
"team_inviteLinkLoading": "Створення вашого посилання",
"team_inviteLinkErrorName": "Будь ласка, додайте ім'я людини, яку ви запрошуєте. Вони можуть змінити його пізніше. ",
"team_inviteLinkCreate": "Створити посилання",
"team_inviteLinkCopy": "Скопіювати посилання",
"team_inviteFrom": "Від:",
"team_invitePleaseLogin": "Будь ласка увійдіть або зареєструйтеся, щоб схвалити запрошення.",
"team_inviteEnterPassword": "Будь ласка, введіть пароль-запрошення, щоб продовжити.",
"team_inviteJoin": "Приєднатися до команди",
"team_inviteTitle": "Запрошення для команди",
"team_inviteGetData": "Отримання даних про команду",
"burnAfterReading_generateLink": "Натисніть на кнопку нижче, щоб згенерувати посилання.",
"burnAfterReading_proceed": "переглянути та видалити",
"burnAfterReading_warningDeleted": "Цей документ було видалено назавжди, після закриття цього вікна ви не зможете отримати до нього доступ.",
"oo_invalidFormat": "Цей файл не можна імпортувати",
"oo_importInProgress": "Імпортування в процесі",
"oo_exportInProgress": "Експортування в процесі",
"oo_sheetMigration_loading": "Оновлення документа до останньої версії. Зачекайте приблизно 1 хвилину.",
"oo_sheetMigration_anonymousEditor": "Доступна оновлена версія, натисніть OK для перезавантаження.",
"profile_login": "Щоб додати цього користувача до своїх контактів, вам потрібно увійти в систему",
"historyTrim_historySize": "Історія: {0}",
"trimHistory_getSizeError": "Помилка під час обчислення розміру історії диска",
"trimHistory_error": "Помилка під час видалення історії",
"trimHistory_needMigration": "Будь ласка <a>оновіть свій CryptDrive</a> щоб увімкнути цю функцію.",
"trimHistory_currentSize": "Поточний розмір історії: <b>{0}</b>",
"owner_request": "{0} хоче, щоб ви стали власником <b>{1}</b>",
"team_leaveButton": "Вийти з команди",
"team_deleteHint": "Видалити команду та всі документи, що належать виключно команді.",
"drive_sfPassword": "Ваша спільна тека {0} більше не доступна. Її або видалено власником, або захищено новим паролем. Ви можете видалити цю папку зі свого CryptDrive або відновити доступ до неї за допомогою нового пароля.",
"requestEdit_confirm": "{1} попросив надати йому можливість редагувати документ <b>{0}</b>. Ви хочете надати йому доступ?",
"owner_removeConfirm": "Ви впевнені, що хочете видалити право власності для вибраних користувачів? Вони отримають сповіщення про цю дію.",
"team_declineInvitation": "{0} відхилив вашу пропозицію приєднатися до команди: <b>{1}</b>",
"team_rosterPromote": "Просувати",
"teams_table_generic_own": "Керування командою: зміна назви та аватарки команди, додавання або видалення Власників, зміна підписки команди, видалення команди.",
"contacts_manageMuted": "Керування приглушеням",
"contacts_muteInfo": "Ви не отримуватимете жодних сповіщень або повідомлень від приглушених користувачів. <br>Вони не знатимуть, що ви їх приглушили. ",
"safeLinks_error": "Це посилання скопійоване з адресного рядка браузера і не надає доступу до документа. Будь ласка використовуйте <i></i> <b>Поділитись</b> щоб поділитися безпосередньо з контактами або скопіювати посилання. <a> Дізнайтеся більше про функцію безпечних посилань</a>.",
"support_notification": "Адміністратор відповів на ваш запит у службу підтримки",
"requestEdit_button": "Запросити права на редагування",
"owner_request_declined": "{0} відхилив вашу пропозицію стати власником <b>{1}</b>",
"team_pcsSelectHelp": "Створення власного документа на диску вашої команди надасть команді право власності на нього.",
"team_leaveConfirm": "Якщо ви покинете цю команду, ви втратите доступ до її CryptDrive, історії чату та іншого вмісту. Ви впевнені?",
"team_ownerConfirm": "Співвласники можуть змінити або видалити команду і видалити вас як власника. Ви впевнені?",
"team_viewers": "Глядачі",
"properties_passwordWarningFile": "Пароль було успішно змінено, але ми не змогли оновити ваш CryptDrive новими даними. Можливо, вам доведеться видалити стару версію файлу вручну.",
"team_inviteLinkWarning": "Люди, які перейдуть за цим посиланням, зможуть приєднатися до цієї групи і переглянути її вміст. Діліться ним обережно.",
"oo_sheetMigration_complete": "Доступна оновлена версія, натисніть OK для перезавантаження.",
"properties_confirmChangeFile": "Ви впевнені? Користувачі без нового пароля втратять доступ до цього файлу.",
"teams_table_specificHint": "Це старі теки зі спільним доступом, де користувачі все ще мають право редагувати наявні документи. Документи, створені або скопійовані у ці теки, матимуть стандартні права доступу.",
"contacts_mutedUsers": "Приглушені акаунти",
"team_inviteFromMsg": "{0} запросив вас до команди <b>{1}</b>",
"team_invitePasswordLoading": "Розшифровка запрошення",
"burnAfterReading_warningLink": "Ви налаштували цей документ на самознищення. Після того, як одержувач перейде за цим посиланням, він зможе переглянути документ один раз, перш ніж його буде остаточно видалено.",
"burnAfterReading_warningAccess": "Цей документ самознищиться. Коли ви натиснете кнопку нижче, ви побачите його вміст один раз, перш ніж він буде видалений назавжди. Коли ви закриєте це вікно, ви більше не зможете отримати до нього доступ. Якщо ви не готові продовжувати, ви можете закрити це вікно і повернутися пізніше.",
"driveOfflineError": "Ваше з'єднання з CryptPad було втрачено. Зміни в цьому документі не будуть збережені на вашому CryptDrive. Будь ласка, закрийте всі вкладки CryptPad і повторіть спробу в новому вікні. ",
"team_inviteLinkSetPassword": "Захистити посилання паролем (рекомендується)",
"historyTrim_contentsSize": "Контакти: {0}",
"access_noContact": "Немає інших контактів для додавання",
"kanban_conflicts": "Наразі редагується:",
"cba_writtenBy": "Надруковано: {0}",
"cba_properties": "Авторські кольори (експериментальні)",
"cba_hint": "Цей параметр буде запам'ятовуватися при створенні наступного документа.",
"cba_enable": "Увімкнути",
"cba_disable": "Очистити та вимкнути",
"cba_show": "Показати кольори автора",
"cba_hide": "Приховати кольори автора",
"oo_login": "Будь ласка, увійдіть або зареєструйтесь, щоб покращити продуктивність електронних таблиць.",
"cba_title": "Авторські кольори",
"comments_notification": "Відповіді на ваш коментар \"{0}\" у <b>{1}</b>",
"history_fastPrev": "Попередній сеанс редагування",
"history_fastNext": "Наступний сеанс редагування",
"snapshots_new": "Новий знімок",
"snapshots_placeholder": "Заголовок знімку",
"snapshot_error_exists": "Вже є знімок цієї версії",
"snapshots_cantMake": "Знімок не вдалося створити. Ви від'єднані від мережі.",
"admin_limitPlan": "План: {0}",
"admin_limitNote": "Примітка: {0}",
"oo_cantMigrate": "Цей аркуш перевищує максимальний розмір завантаження і є занадто великим для перенесення.",
"admin_supportPrivTitle": "Підтримка приватного ключа поштової скриньки",
"support_premiumLink": "Переглянути варіанти підписки",
"snaphot_title": "Знімок",
"profile_defaultAlt": "Зображення профілю за замовчуванням",
"snapshots_ooPickVersion": "Перед створенням знімка необхідно вибрати версію",
"team_leaveOwner": "Будь ласка, понизьте себе в ролі власника перед тим, як покинути команду. Зверніть увагу, що команда повинна мати принаймні одного власника, будь ласка, додайте ще одного перед тим, як продовжити, якщо ви наразі єдиний власник.",
"support_premiumPriority": "Преміум користувачі допомагають покращувати зручність використання CryptPad і отримують пріоритетні відповіді на свої запити в службу підтримки.",
"unknownPad": "Невідомий документ",
"mentions_notification": "{0} згадали вас у <b>{1}</b>",
"comments_deleted": "Коментар видалено автором",
"comments_edited": "Змінено",
"comments_submit": "Надіслати",
"comments_reply": "Відповісти",
"comments_resolve": "Розвʼязати",
"comments_comment": "Коментар",
"comments_error": "Не вдалося додати коментар",
"fm_sort": "Впорядкувати",
"code_editorTheme": "Вигляд редактора",
"support_cat_data": "Втрата вмісту",
"support_cat_bug": "Звіт про ваду",
"support_cat_other": "Інше",
"support_cat_all": "Усе",
"support_attachments": "Вкладення",
"support_addAttachment": "Додати вкладення",
"notification_fileSharedTeam": "{0} поділилися файлом із командою {2}: <b>{1}</b>",
"notification_folderSharedTeam": "{0} поділилися текою з командою {2}: <b>{1}</b>",
"support_category": "Оберіть тип",
"support_formCategoryError": "Помилка: тип порожній",
"fm_restricted": "Ви не маєте доступу",
"fm_noResult": "Нічого не знайдено",
"history_cantRestore": "Відновити не вдалося. Ви відʼєднані.",
"history_userPrev": "Попередній автор",
"history_userNext": "Наступний автор",
"history_restoreDriveTitle": "Відновити обрану версію CryptDrive",
"history_restoreDrivePrompt": "Упевнені, що хочете замінити поточну версію CryptDrive показаною версією?",
"snapshots_open": "Відкрити",
"snapshots_restore": "Відновити",
"snapshots_close": "Закрити",
"snapshots_delete": "Видалити",
"team_exportTitle": "Завантажити сховище команди",
"team_exportButton": "Завантажити",
"fm_deletedFolder": "Видалити теку",
"fm_shareFolderPassword": "Захистити цю теку паролем (не обовʼязково)",
"error_unhelpfulScriptError": "Помилка скрипту: Дивіться консоль браузера для подробиць",
"fileTableHeader": "Завантаження й вивантаження",
"download_zip_file": "Файл {0}/{1}",
"admin_support_premium": "Преміум квитки:",
"admin_support_normal": "Квитки без відповіді:",
"admin_support_answered": "Квитки з відповіддю:",
"admin_support_closed": "Закриті квитки:",
"admin_support_open": "Показувати",
"admin_support_collapse": "Згорнути",
"admin_support_first": "Створено: ",
"admin_support_last": "Оновлено: ",
"addOptionalPassword": "Додати пароль (не обовʼязково)",
"fm_cantUploadHere": "Не вдалося завантажити файл сюди",
"settings_deleteContinue": "Видалити мою обліковку",
"settings_deleteSubscription": "Керувати підпискою",
"calendar_dateTimeRange": "{0} {1} - {2}",
"calendar_noNotification": "Порожньо",
"oo_conversionSupport": "Ваш оглядач не підтримує перетворення офісного формату. Ми радимо користати останню версію Firefox або Chrome.",
"admin_supportPrivButton": "Показати ключ",
"calendar_more": "{0} більше",
"mdToolbar_embed": "Вмостити файл",
"admin_updateAvailableTitle": "Нова версія",
"admin_updateAvailableHint": "Доступна нова версія CryptPad",
"admin_updateAvailableButton": "Огляньте примітки випуску",
"admin_provideAggregateStatisticsLabel": "Надавати збірну статистику",
"resources_imageBlocked": "CryptPad заблокував віддалене зображення",
"resources_openInNewTab": "Відкрити у новій вкладці",
"resources_learnWhy": "Дізнатися, чому це заблоковано",
"notification_openLink": "Ви одержали посилання <b>{0}</b> від {1}:",
"notification_linkShared": "{0} поділились посиланням із вами: <b>{1}</b>",
"offlineError": "Не вдалося синхронізувати недавні дані, зараз неможливо показати цю сторінку. Завантаження продовжиться, коли ваше зʼєднання з сервісом буде відновлено.",
"support_languagesPreamble": "Підтримка розуміє такі мови:",
"fm_emptyTrashOwned": "Ваш смітник містить документи у вашій власности. Ви можете <b>усунути</b> їх лише з вашого сховища, або <b>знищити</b> їх для усіх користувачів.",
"team_exportHint": "Завантажити усі документи у сховищі цієї команди. Документи будуть завантажені у форматі, придатному до читання іншими застосунками, коли такий формат є доступним. В іншому випадку, документи будуть завантажені у форматі, придатний до читання CryptPad.",
"download_zip": "Збирання файлу ZIP…",
"oo_lostEdits": "На жаль, не вдалося відновити ваші недавньо збережені зміни після надходження нового вмісту.",
"toolbar_degraded": "Понад {0} правників наразі присутні в документі. Перелік користувачів та чат вимкнено для підвищення продуктивності.",
"notification_padSharedTeam": "{0} поділилися документом із командою {2}: <b>{1}</b>",
"settings_deleteWarning": "Увага: наразі ви є передплатником(-цею) преміум-плану (оплачено або дано іншим користувачем). Будь ласка, скасуйте ваш план перед видаленням обліковки, бо після видалення це неможливо буде зробити без звернення до підтримки.",
"oo_importBin": "Натисніть «Гаразд», щоби імпортувати внутрішній формат .bin.",
"restrictedLoginPrompt": "Ви не можете переглянути цей документ. <a>Увійдіть</a>, якщо вважаєте, що ваша обліковка має до цього доступ.",
"admin_provideAggregateStatisticsTitle": "Збір статистики",
"share_versionHash": "Ви збираєтесь поділитися обраною версією документу в режимі лише для читання. Це також <b>надасть право на перегляд</b> для всіх версій документу.",
"unableToDisplay": "Не вдалося показати документ. Натисніть Esc, щоби перезавантажити сторінку. Якщо проблема не мине, звʼяжіться з підтримкою.",
"history_trimPrompt": "Цей документ має історію, довжиною в {0}, що може спричинити повільне завантаження. Очистіть історію, якщо вона не потрібна.",
"admin_provideAggregateStatisticsHint": "Ви можете погодитись надавати додаткові дані використання розробникам, як-от приблизну кількість зареєстрованих та щоденних користувачів на вашому примірнику.",
"fc_open_formro": "Відкрити (як учасник)",
"upload_modal_alt": "Альтернативний текст",
"upload_addOptionalAlt": "Додайте описовий текст (необов'язково)",
"admin_supportPrivHint": "Відображати закритий ключ, який знадобиться іншим адміністраторам для перегляду запитів служби підтримки. На панелі адміністратора відобразиться форма для введення цього ключа.",
"fc_openIn": "Відкрити в {0}",
"download_step3": "Перетворення...",
"earlyAccessBlocked": "Ця програма поки що недоступна на цьому екземплярі",
"admin_archiveNote": "Примітка",
"support_warning_account": "Зверніть увагу, що адміністратори не можуть скинути паролі. Якщо ви втратили облікові дані свого облікового запису, але все ще маєте активний сеанс, ви можете <a>перенести свої дані в новий обліковий запис</a>",
"support_warning_document": "Укажіть тип документа, який викликає проблему, і надайте <a>ідентифікатор документа</a> або посилання",
"premiumOnly": "Створення нових документів у цьому додатку наразі обмежено для підписників на {0}. Це експериментальний додаток з раннім доступом для тестування. Незабаром він стане доступним для всіх в {0}.",
"bounce_confirm": "Ви збираєтеся залишити: {0}\n\nВи впевнені, що бажаєте відвідати \"{1}\"?",
"support_warning_drives": "Зауважте, що адміністратори не можуть ідентифікувати теки та документи за назвою. Для спільних тек надайте <a>ідентифікатор документа</a>",
"premiumAccess": "Як підписник на {0}, ви можете створювати нові документи в цьому додатку з раннім доступом. Будь ласка, зауважте, що він є експериментальним і поки що не варто довіряти йому важливі дані.",
"support_warning_prompt": "Будь ласка, виберіть найбільш відповідну категорію для вашої проблеми. Це допомагає адміністраторам сортувати та надає додаткові пропозиції щодо інформації, яку потрібно надати",
"support_warning_bug": "Будь ласка, вкажіть, у якому браузері виникає проблема та чи встановлено якісь розширення. Надайте якомога більше деталей про проблему та кроки, необхідні для її відтворення",
"bounce_danger": "Посилання, яке ви натиснули, веде не на веб-сторінку, а на певний код або дані, які можуть бути шкідливими.\n\n(\"{0}\")\n\nCryptPad блокує їх з міркувань безпеки. Натиснувши OK, ви закриєте цю вкладку.",
"support_warning_abuse": "Повідомте про вміст, який порушує <a>Загальні положення та умови</a>. Надайте посилання на образливі документи або профілі користувачів і опишіть, як вони порушують умови. Будь-яка додаткова інформація про контекст, у якому ви виявили вміст або поведінку, може допомогти адміністраторам запобігти майбутнім порушенням",
"support_cat_document": "Документ",
"support_warning_other": "Який характер вашого запиту? Надайте якомога більше відповідної інформації, щоб нам було легше швидко вирішити вашу проблему",
"support_cat_abuse": "Повідомити про зловживання",
"ui_openDirectly": "Ця функціональність недоступна, якщо CryptPad вбудовано в інший сайт. Відкрити цей документ у новій вкладці?",
"support_cat_debugging": "Дані налагодження",
"support_debuggingDataTitle": "Інформація про налагодження облікового запису",
"fivehundred_internalServerError": "Внутрішня помилка сервера",
"home_morestorage": "Щоб отримати більше місця для зберігання:",
"login_instance": "Підключіться до свого облікового запису на {0}",
"footer_website": "Вебсторінка проєкту",
"register_instance": "Створити новий обліковий запис на {0}",
"admin_uptimeTitle": "Час запуску",
"admin_noticeTitle": "Примітки домашнього екрана",
"admin_generatedAt": "Час звіту",
"ui_false": "брехня",
"ui_undefined": "невідомо",
"ui_none": "немає",
"ui_success": "Успіх",
"ui_fetch": "Отримати",
"ui_confirm": "Підтвердити",
"admin_restoreReason": "Будь ласка, вкажіть причину відновлення та підтвердьте, що ви бажаєте продовжити",
"admin_accountMetadataTitle": "Інформація про обліковий запис",
"admin_documentMetadataTitle": "Інформація про документ",
"admin_documentMetadataHint": "Запитувати документ або файл за його ідентифікатором або URL-адресою",
"admin_documentSize": "Розмір документа",
"admin_documentMetadata": "Поточні метадані",
"admin_documentCreationTime": "Створено",
"admin_currentlyOpen": "Наразі відкрито",
"admin_channelAvailable": "Доступно",
"admin_channelArchived": "Архівовано",
"admin_documentModifiedTime": "Остання зміна",
"admin_documentMetadataPlaceholder": "Посилання на документ або його ідентифікатор",
"home_location": "Зашифровані дані зберігаються в {0}",
"ui_true": "правда",
"admin_archiveReason": "Будь ласка, вкажіть причину архівування та підтвердьте, що ви бажаєте продовжити",
"admin_accountMetadataHint": "Введіть відкритий ключ користувача, щоб отримати дані про його обліковий запис.",
"admin_noticeHint": "Додаткове повідомлення для відображення на головній сторінці",
"admin_cat_database": "База даних",
"support_debuggingDataHint": "Наступна інформація міститься в заявках у службу підтримки, які ви надсилаєте. Жоден із них не дозволяє адміністраторам отримати доступ або розшифрувати ваші документи. Ця інформація зашифрована таким чином, що її можуть прочитати лише адміністратори.",
"admin_uptimeHint": "Дата і час запуску сервера",
"ui_generateReport": "Згенерувати звіт",
"admin_lastPinTime": "Час останньої активності шпильки",
"admin_blockMetadataHint": "Блок входу — це те, що дозволяє обліковому запису входити в CryptPad за допомогою комбінації імені користувача та пароля",
"admin_blockMetadataTitle": "Інформація про блок входу",
"admin_blockMetadataPlaceholder": "Абсолютний або відносний блок URL",
"admin_accountMetadataPlaceholder": "Ідентифікатор користувача (відкритий ключ підпису)",
"admin_currentlyOnline": "Зараз онлайн",
"admin_planName": "Назва плану",
"admin_note": "Примітка плану",
"admin_storageUsage": "Дані збережені",
"admin_channelCount": "Кількість документів",
"admin_fileCount": "Кількість файлів",
"admin_blockKey": "Заблокувати відкритий ключ",
"admin_firstPinTime": "Час першої активності шпильки",
"admin_blockAvailable": "Блок доступний",
"admin_blockArchived": "Блок заархівовано",
"admin_archiveBlock": "Заархівувати блок",
"admin_restoreBlock": "Відновити заархівований блок",
"admin_archiveDocument": "Заархівувати документ",
"admin_restoreDocument": "Відновити документ",
"admin_planlimit": "Обмеження сховища",
"admin_reportContent": "Повідомити про вміст",
"admin_getRawMetadata": "Історія метаданих",
"og_register": "Створити обліковий запис на {0}",
"og_encryptedAppType": "Зашифровано {0}",
"admin_documentConflict": "Заархівувати/відновити",
"fm_rmFilter": "Вилучити фільтр",
"fm_filterBy": "Фільтр",
"calendar_rec": "Повторити",
"calendar_rec_no": "Одноразово",
"calendar_rec_updated": "Роль оновлено на {0}",
"calendar_rec_daily": "Щодня",
"calendar_rec_stop": "Зупинити повторення",
"calendar_rec_weekly": "Щотижня в {0}",
"calendar_rec_edit_all": "Редагувати всі події",
"calendar_rec_monthly": "Щомісяця, день {1}",
"calendar_rec_edit_from": "Редагувати майбутні події",
"calendar_rec_yearly": "Щорічно в {2}",
"calendar_rec_edit_one": "Редагувати тільки цю подію",
"calendar_rec_weekend": "Щодня у вихідні дні",
"calendar_rec_edit": "Це повторювана подія",
"calendar_str_filter_day": "Дні: {0}",
"calendar_rec_weekdays": "Щодня по буднях",
"calendar_str_filter_monthday": "Дні місяця: {0}",
"calendar_rec_custom": "Користувача",
"calendar_str_filter_yearday": "Дні року: {0}",
"calendar_str_filter_month": "Місяці: {0}",
"calendar_str_filter": "Фільтри:",
"calendar_rec_freq_daily": "дні",
"calendar_rec_freq_weekly": "тижні",
"calendar_rec_freq_monthly": "місяці",
"calendar_str_for": "протягом {0} разів",
"calendar_rec_freq_yearly": "роки",
"calendar_rec_until_no": "Ніколи",
"calendar_str_day": "на {0}",
"calendar_str_daily": "{0} день(ів)",
"calendar_rec_until_count": "Після",
"calendar_str_weekly": "{0} тиждень(ів)",
"calendar_str_yearly": "{0} рік(ів)",
"og_login": "Увійти до {0}",
"og_contact": "{0} Контакт",
"ui_jsRequired": "Для виконання шифрування у вашому браузері має бути ввімкнено JavaScript",
"admin_conflictExplanation": "Існує дві версії цього документа. Відновлення архівної версії замінить актуальну версію. Архівування поточної версії замінить архівовану версію. Жодна з цих дій не може бути скасована.",
"calendar_str_filter_weekno": "Тижні: {0}",
"calendar_rec_until": "Зупинити повторення",
"calendar_str_monthly": "{0} місяць(ів)",
"calendar_rec_until_count2": "рази",
"calendar_rec_monthly_pick": "По днях",
"calendar_nth_1": "перше",
"calendar_list_end": "{0} чи {1}",
"calendar_nth_2": "друге",
"calendar_list": "{0}, {1}",
"calendar_nth_3": "третє",
"calendar_nth_4": "четверте",
"calendar_rec_every_date": "Кожні {0}",
"calendar_month_last": "останній день"
}

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