Merge branch 'staging' into inactive-accounts

This commit is contained in:
ansuz 2020-09-28 17:56:30 +05:30
commit a9b95865ba
39 changed files with 1926 additions and 1188 deletions

1
.gitignore vendored
View File

@ -1,6 +1,7 @@
datastore
tasks
www/bower_components/*
www/accounts
node_modules
/config.js
customization

View File

@ -15,6 +15,7 @@ www/common/onlyoffice/v2*
server.js
www/common/old-media-tag.js
www/scratch
www/accounts
www/lib
www/accounts

View File

@ -1,3 +1,31 @@
# WoollyMammoth (3.22.0)
## Goals
We've been working on some long-term projects that we hope to deliver over the course of the next few releases. In the meantime, this release includes a number of minor improvements.
## Update notes
To upgrade from 3.21.0 to 3.22.0:
1. Stop your server
2. Get the latest platform code with git
3. Install client-side dependencies with `bower update`
4. Restart the CryptPad API server
## Features
* Contributors have helped by translating more of CryptPad into Finnish and traditional Chinese via [our weblate instance](https://weblate.cryptpad.fr/projects/cryptpad/app/)
* We've updated the syntax highlighting code that we use throughout the platform to include Rustlang (and possibly other languages that have been updated in the meantime).
* You can now use _ctrl-f_ in user or team drives to jump immediately to the search interface instead of possibly scrolling up to click on its entry in the sidebar.
## Bug fixes
* Some of the special behaviour implemented for Org-mode in our code editor sometimes failed when the document was first changed into Org-mode.
* We now clear some minor personal preferences like whether certain tooltips had been dismissed when you log out.
* We identified and addressed a number of issues with teams that caused valid teams to not be displayed and team member rights to fail to upgrade until a full session reload.
* We now display the number of days before an unregistered user's documents are considered inactive in their drive instead of hardcoding "3 months".
# VietnameseRhinoceros (3.21.0)
## Goals

View File

@ -205,3 +205,11 @@ a > img {
.cp-link-clicked a {
cursor: pointer;
}
media-tag {
display: inline-block;
}
media-tag * {
width: 100%;
height: 100%;
}

View File

@ -5,7 +5,7 @@ var map = {
'de': 'Deutsch',
'el': 'Ελληνικά',
'es': 'Español',
'fi': 'Suomalainen',
'fi': 'Suomi',
'fr': 'Français',
//'hi': 'हिन्दी',
'it': 'Italiano',

View File

@ -62,7 +62,7 @@ define([
var imprintUrl = AppConfig.imprint && (typeof(AppConfig.imprint) === "boolean" ?
'/imprint.html' : AppConfig.imprint);
Pages.versionString = "CryptPad v3.21.0 (VietnameseRhinoceros)";
Pages.versionString = "CryptPad v3.22.0 (WoollyMammoth)";
// used for the about menu
Pages.imprintLink = AppConfig.imprint ? footLink(imprintUrl, 'imprint') : undefined;

View File

@ -153,12 +153,10 @@
max-width: 500px;
margin: 0 auto;
text-align: left;
padding: @alertify_padding-base;
background: #fff;
box-shadow: @alertify_box-shadow;
&.wide {
width: 1000px;
max-width: 70%;
max-width: 850px;
}
}
@ -178,13 +176,14 @@
max-height: 100%;
display: flex;
flex-flow: column;
padding: @alertify_padding-base;
.alertify-tabs-titles {
height: 40px;
display: flex;
border-bottom: 1px solid @alertify-fore;
margin-bottom: 10px;
box-sizing: content-box;
span {
.alertify-tabs-title {
.tools_unselectable();
font-size: 20px;
height: 40px;
@ -201,6 +200,13 @@
color: #949494;
cursor: not-allowed;
}
&:not(.alertify-tabs-active) {
@media (max-width: @browser_media-medium-screen) {
.tab-title-text {
display: none;
}
}
}
}
span.alertify-tabs-active {
background-color: @alertify-fore !important;
@ -393,9 +399,15 @@
.cp-share-columns {
display: flex;
flex-flow: row;
@media screen and (max-width: (@browser_media-medium-screen)) {
flex-flow: column;
}
& > .cp-share-column {
width: 50%;
@media screen and (max-width: (@browser_media-medium-screen)) {
width: unset;
}
//padding: 0 10px;
position: relative;
&.contains-nav {
@ -414,19 +426,32 @@
}
&:first-child {
margin-right: @alertify_padding-base;
@media screen and (max-width: (@browser_media-medium-screen)) {
margin: 0 0 @alertify_padding-base 0;
}
}
&:last-child {
margin-left: @alertify_padding-base;
@media screen and (max-width: (@browser_media-medium-screen)) {
margin: 0px;
}
}
}
& > .cp-share-column-mid {
display: flex;
align-items: center;
justify-content: center;
@media screen and (max-width: (@browser_media-medium-screen)) {
margin-bottom: @alertify_padding-base;
}
button {
width: 50px;
margin: 0;
min-width: 0;
font-size: 18px !important;
@media screen and (max-width: (@browser_media-medium-screen)) {
width: 100%;
}
}
}
}

View File

@ -89,6 +89,7 @@
}
&.cp-corner-big {
width: 500px;
max-width: 95%;
}
.cp-corner-dontshow {

View File

@ -41,6 +41,7 @@
box-shadow: @variables_shadow;
padding: @variables_padding;
padding-top: @variables_padding * 2;
position: relative;
//top: 15vh; bottom: 15vh;
@ -57,6 +58,11 @@
margin-bottom: 1em;
}
& > p:not(.cp-modal-form) {
text-align: left; // XXX needs testing
margin-right: 30px;
}
.cp-modal-form {
display: flex;
flex-wrap: wrap;

View File

@ -1,5 +1,7 @@
@import (reference) "./colortheme-all.less";
@import (reference) "./variables.less";
@import (reference) "./browser.less";
.modals-ui-elements_main() {
--LessLoader_require: LessLoader_currentFile();
}
@ -20,6 +22,15 @@
.cp-radio {
margin-right: 30px;
}
@media (max-width: @browser_media-medium-screen) {
flex-direction: column;
&:not(:last-child) {
margin-bottom: 0px;
}
.cp-radio {
margin: 0 0 5px 0;
}
}
}
}
@ -74,6 +85,24 @@
}
// Access modal
button.cp-access-add {
i {
margin-right: 0px !important;
}
i.fa-arrow-left {
display: inline;
@media (max-width: @browser_media-medium-screen) {
display: none;
}
}
i.fa-arrow-up {
display: none;
@media (max-width: @browser_media-medium-screen) {
display: inline;
}
}
}
.cp-overlay-container {
position: relative;
.cp-overlay {

View File

@ -146,6 +146,33 @@ var flushCache = function (Env, Server, cb) {
cb(void 0, true);
};
// CryptPad_AsyncStore.rpc.send('ADMIN', ['ARCHIVE_DOCUMENT', documentID], console.log)
var archiveDocument = function (Env, Server, cb, data) {
var id = Array.isArray(data) && data[1];
if (typeof(id) !== 'string' || id.length < 32) { return void cb("EINVAL"); }
switch (id.length) {
case 32:
// TODO disconnect users from active sessions
return void Env.msgStore.archiveChannel(id, cb);
case 48:
return void Env.blobStore.archive.blob(id, cb);
default:
return void cb("INVALID_ID_LENGTH");
}
// archival for blob proofs isn't automated, but evict-inactive.js will
// clean up orpaned blob proofs
// Env.blobStore.archive.proof(userSafeKey, blobId, cb)
};
var restoreArchivedDocument = function (Env, Server, cb) {
// Env.msgStore.restoreArchivedChannel(channelName, cb)
// Env.blobStore.restore.blob(blobId, cb)
// Env.blobStore.restore.proof(userSafekey, blobId, cb)
cb("NOT_IMPLEMENTED");
};
// CryptPad_AsyncStore.rpc.send('ADMIN', ['SET_DEFAULT_STORAGE_LIMIT', 1024 * 1024 * 1024 /* 1GB */], console.log)
var setDefaultStorageLimit = function (Env, Server, cb, data) {
@ -174,6 +201,9 @@ var commands = {
GET_FILE_DESCRIPTOR_LIMIT: getFileDescriptorLimit,
SET_DEFAULT_STORAGE_LIMIT: setDefaultStorageLimit,
GET_CACHE_STATS: getCacheStats,
ARCHIVE_DOCUMENT: archiveDocument,
RESTORE_ARCHIVED_DOCUMENT: restoreArchivedDocument,
};
Admin.command = function (Env, safeKey, data, _cb, Server) {

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "cryptpad",
"version": "3.21.0",
"version": "3.22.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@ -1,7 +1,7 @@
{
"name": "cryptpad",
"description": "realtime collaborative visual editor with zero knowlege server",
"version": "3.21.0",
"version": "3.22.0",
"license": "AGPL-3.0+",
"repository": {
"type": "git",

View File

@ -134,6 +134,16 @@ define([
framework._.toolbar.$drawer.append(helpMenu.button);
};
var previews = {};
previews['gfm'] = function (val, $div, common) {
DiffMd.apply(DiffMd.render(val), $div, common);
};
previews['markdown'] = previews['gfm'];
previews['htmlmixed'] = function (val, $div, common) {
DiffMd.apply(val, $div, common);
};
var mkPreviewPane = function (editor, CodeMirror, framework, isPresentMode) {
var $previewContainer = $('#cp-app-code-preview');
var $preview = $('#cp-app-code-preview-content');
@ -149,17 +159,19 @@ define([
var $previewButton = framework._.sfCommon.createButton('preview', true);
var forceDrawPreview = function () {
var f = previews[CodeMirror.highlightMode];
if (!f) { return; }
try {
if (editor.getValue() === '') {
$previewContainer.addClass('cp-app-code-preview-isempty');
return;
}
$previewContainer.removeClass('cp-app-code-preview-isempty');
DiffMd.apply(DiffMd.render(editor.getValue()), $preview, framework._.sfCommon);
f(editor.getValue(), $preview, framework._.sfCommon);
} catch (e) { console.error(e); }
};
var drawPreview = Util.throttle(function () {
if (['markdown', 'gfm'].indexOf(CodeMirror.highlightMode) === -1) { return; }
if (!previews[CodeMirror.highlightMode]) { return; }
if (!$previewButton.is('.cp-toolbar-button-active')) { return; }
forceDrawPreview();
}, 400);
@ -171,7 +183,7 @@ define([
previewTo = setTimeout(function () {
$codeMirror.removeClass('transition');
}, 500);
if (['markdown', 'gfm'].indexOf(CodeMirror.highlightMode) === -1) {
if (!previews[CodeMirror.highlightMode]) {
$previewContainer.show();
}
$previewContainer.toggle();
@ -213,7 +225,7 @@ define([
});
var modeChange = function (mode) {
if (['markdown', 'gfm'].indexOf(mode) !== -1) {
if (previews[mode]) {
$previewButton.show();
framework._.sfCommon.getPadAttribute('previewMode', function (e, data) {
if (e) { return void console.error(e); }
@ -273,7 +285,7 @@ define([
// keep trying to draw until you're confident it has been drawn
previewInt = setInterval(function () {
// give up if it's not a valid preview mode
if (['markdown', 'gfm'].indexOf(CodeMirror.highlightMode) === -1) { return void clear(); }
if (!previews[CodeMirror.highlightMode]) { return void clear(); }
// give up if content has been drawn
if ($preview.text()) { return void clear(); }
// only draw if there is actually content to display

View File

@ -123,7 +123,10 @@ define([
};
});
var init = false;
CodeMirror.registerHelper("orgmode", "init", function (editor) {
if (init) { return; }
editor.setOption("extraKeys", {
"Tab": function(cm) { org_cycle(cm); },
"Shift-Tab": function(cm){ org_shifttab(cm); },
@ -139,6 +142,7 @@ define([
"Shift-Right": function(cm){ org_shiftright(cm); }
});
init = true;
editor.on('mousedown', toggleHandler);
editor.on('touchstart', toggleHandler);
editor.on('gutterClick', foldLine);
@ -155,6 +159,9 @@ define([
});
CodeMirror.registerHelper("orgmode", "destroy", function (editor) {
if (!init) { return; }
init = false;
editor.off('mousedown', toggleHandler);
editor.off('touchstart', toggleHandler);
editor.off('gutterClick', foldLine);

View File

@ -221,9 +221,9 @@ define([
tabs.forEach(function (tab, i) {
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' : ''), tab.title);
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));
if (tab.icon) {
var icon = h('i', {class: tab.icon});
var icon = h('i', {class: tab.icon, 'aria-labelledby': 'cp-tab-' + tab.title.toLowerCase()});
$(title).prepend(' ').prepend(icon);
}
$(title).click(function () {

View File

@ -229,181 +229,7 @@ define([
};
};
var createShareWithFriends = function (config, onShare, linkGetter) {
var common = config.common;
var sframeChan = common.getSframeChannel();
var title = config.title;
var friends = config.friends || {};
var teams = config.teams || {};
var myName = common.getMetadataMgr().getUserData().name;
var order = [];
var smallCurves = Object.keys(friends).map(function (c) {
return friends[c].curvePublic.slice(0,8);
});
var div = h('div.contains-nav');
var $div = $(div);
// Replace "copy link" by "share with friends" if at least one friend is selected
// Also create the "share with friends" button if it doesn't exist
var refreshButtons = function () {
var $nav = $div.closest('.alertify').find('nav');
var friendMode = $div.find('.cp-usergrid-user.cp-selected').length;
if (friendMode) {
$nav.find('button.cp-share-with-friends').prop('disabled', '');
} else {
$nav.find('button.cp-share-with-friends').prop('disabled', 'disabled');
}
};
config.noInclude = true;
Object.keys(friends).forEach(function (curve) {
var data = friends[curve];
if (curve.length > 40 && data.notifications) { return; }
delete friends[curve];
});
var others = [];
if (Object.keys(friends).length) {
var friendsList = UIElements.getUserGrid(Messages.share_linkFriends, {
common: common,
data: friends,
noFilter: false,
large: true
}, refreshButtons);
var friendDiv = friendsList.div;
$div.append(friendDiv);
others = friendsList.icons;
}
if (Object.keys(teams).length) {
var teamsList = UIElements.getUserGrid(Messages.share_linkTeam, {
common: common,
noFilter: true,
large: true,
data: teams
}, refreshButtons);
$div.append(teamsList.div);
}
var shareButton = {
className: 'primary cp-share-with-friends',
name: Messages.share_withFriends,
onClick: function () {
var href;
NThen(function (waitFor) {
var w = waitFor();
// linkGetter can be async if this is a burn after reading URL
var res = linkGetter({}, function (url) {
if (!url) {
waitFor.abort();
return;
}
href = url;
setTimeout(w);
});
if (res && /^http/.test(res)) {
href = Hash.getRelativeHref(res);
setTimeout(w);
return;
}
}).nThen(function () {
var $friends = $div.find('.cp-usergrid-user.cp-selected');
$friends.each(function (i, el) {
var curve = $(el).attr('data-curve');
var ed = $(el).attr('data-ed');
var friend = curve && friends[curve];
var team = teams[ed];
// If the selected element is a friend or a team without edit right,
// send a notification
var mailbox = friend || ((team && team.viewer) ? team : undefined);
if (mailbox) { // Friend
if (friends[curve] && !mailbox.notifications) { return; }
if (mailbox.notifications && mailbox.curvePublic) {
common.mailbox.sendTo("SHARE_PAD", {
href: href,
password: config.password,
isTemplate: config.isTemplate,
name: myName,
title: title
}, {
viewed: team && team.id,
channel: mailbox.notifications,
curvePublic: mailbox.curvePublic
});
return;
}
}
// If it's a team with edit right, add the pad directly
if (!team) { return; }
sframeChan.query('Q_STORE_IN_TEAM', {
href: href,
password: config.password,
path: config.isTemplate ? ['template'] : undefined,
title: title,
teamId: team.id
}, function (err) {
if (err) { return void console.error(err); }
});
});
UI.findCancelButton().click();
// Update the "recently shared with" array:
// Get the selected curves
var curves = $friends.toArray().map(function (el) {
return ($(el).attr('data-curve') || '').slice(0,8);
}).filter(function (x) { return x; });
// Prepend them to the "order" array
Array.prototype.unshift.apply(order, curves);
order = Util.deduplicateString(order);
// Make sure we don't have "old" friends and save
order = order.filter(function (curve) {
return smallCurves.indexOf(curve) !== -1;
});
common.setAttribute(['general', 'share-friends'], order);
if (onShare) {
onShare.fire();
}
});
},
keys: [13]
};
common.getAttribute(['general', 'share-friends'], function (err, val) {
order = val || [];
// Sort friends by "recently shared with"
others.sort(function (a, b) {
var ca = ($(a).attr('data-curve') || '').slice(0,8);
var cb = ($(b).attr('data-curve') || '').slice(0,8);
if (!ca && !cb) { return 0; }
if (!ca) { return 1; }
if (!cb) { return -1; }
var ia = order.indexOf(ca);
var ib = order.indexOf(cb);
if (ia === -1 && ib === -1) { return 0; }
if (ia === -1) { return 1; }
if (ib === -1) { return -1; }
return ia - ib;
});
// Reorder the friend icons
others.forEach(function (el, i) {
$(el).attr('data-order', i).css('order', i);
});
// Display them
$(friendDiv).find('.cp-usergrid-grid').detach();
$(friendDiv).append(h('div.cp-usergrid-grid', others));
refreshButtons();
});
return {
content: div,
buttons: [shareButton]
};
};
var noContactsMessage = function(common){
UIElements.noContactsMessage = function (common) {
var metadataMgr = common.getMetadataMgr();
var data = metadataMgr.getUserData();
var origin = metadataMgr.getPrivateData().origin;
@ -446,655 +272,6 @@ define([
}
};
var getEditableTeams = function (common, config) {
var privateData = common.getMetadataMgr().getPrivateData();
var teamsData = Util.tryParse(JSON.stringify(privateData.teams)) || {};
var teams = {};
Object.keys(teamsData).forEach(function (id) {
// config.teamId only exists when we're trying to share a pad from a team drive
// In this case, we don't want to share the pad with the current team
if (config.teamId && config.teamId === id) { return; }
var t = teamsData[id];
teams[t.edPublic] = {
viewer: !teamsData[id].hasSecondaryKey,
notifications: t.notifications,
curvePublic: t.curvePublic,
displayName: t.name,
edPublic: t.edPublic,
avatar: t.avatar,
id: id
};
});
return teams;
};
var makeBurnAfterReadingUrl = function (common, href, channel, cb) {
var keyPair = Hash.generateSignPair();
var parsed = Hash.parsePadUrl(href);
var newHref = parsed.getUrl({
ownerKey: keyPair.safeSignKey
});
var sframeChan = common.getSframeChannel();
var rtChannel;
NThen(function (waitFor) {
if (parsed.type !== "sheet") { return; }
common.getPadAttribute('rtChannel', waitFor(function (err, chan) {
rtChannel = chan;
}));
}).nThen(function (waitFor) {
sframeChan.query('Q_SET_PAD_METADATA', {
channel: channel,
command: 'ADD_OWNERS',
value: [keyPair.validateKey]
}, waitFor(function (err) {
if (err) {
waitFor.abort();
UI.warn(Messages.error);
}
}));
if (rtChannel) {
sframeChan.query('Q_SET_PAD_METADATA', {
channel: rtChannel,
command: 'ADD_OWNERS',
value: [keyPair.validateKey]
}, waitFor(function (err) {
if (err) {
console.error(err);
}
}));
}
}).nThen(function () {
cb(newHref);
});
};
UIElements.createShareModal = function (config) {
var origin = config.origin;
var pathname = config.pathname;
var hashes = config.hashes;
var common = config.common;
if (!hashes || (!hashes.editHash && !hashes.viewHash)) { return; }
// check if the pad is password protected
var hash = hashes.editHash || hashes.viewHash;
var href = origin + pathname + '#' + hash;
var parsedHref = Hash.parsePadUrl(href);
var hasPassword = parsedHref.hashData.password;
var makeFaqLink = function () {
var link = h('span', [
h('i.fa.fa-question-circle'),
h('a', {href: '#'}, Messages.passwordFaqLink)
]);
$(link).click(function () {
common.openURL(config.origin + "/faq.html#security-pad_password");
});
return link;
};
var parsed = Hash.parsePadUrl(pathname);
var canPresent = ['code', 'slide'].indexOf(parsed.type) !== -1;
var canBAR = parsed.type !== 'drive';
var burnAfterReading = (hashes.viewHash && canBAR) ?
UI.createRadio('accessRights', 'cp-share-bar', Messages.burnAfterReading_linkBurnAfterReading, false, {
mark: {tabindex:1},
label: {style: "display: none;"}
}) : undefined;
var rights = h('div.msg.cp-inline-radio-group', [
h('label', Messages.share_linkAccess),
h('div.radio-group',[
UI.createRadio('accessRights', 'cp-share-editable-false',
Messages.share_linkView, true, { mark: {tabindex:1} }),
canPresent ? UI.createRadio('accessRights', 'cp-share-present',
Messages.share_linkPresent, false, { mark: {tabindex:1} }) : undefined,
UI.createRadio('accessRights', 'cp-share-editable-true',
Messages.share_linkEdit, false, { mark: {tabindex:1} })]),
burnAfterReading
]);
// Burn after reading
// Check if we are an owner of this pad. If we are, we can show the burn after reading option.
// When BAR is selected, display a red message indicating the consequence and add
// the options to generate the BAR url
var barAlert = h('div.alert.alert-danger.cp-alertify-bar-selected', {
style: 'display: none;'
}, Messages.burnAfterReading_warningLink);
var channel = Hash.getSecrets('pad', hash, config.password).channel;
common.getPadMetadata({
channel: channel
}, function (obj) {
if (!obj || obj.error) { return; }
var priv = common.getMetadataMgr().getPrivateData();
// Not an owner: don't display the burn after reading option
if (!Array.isArray(obj.owners) || obj.owners.indexOf(priv.edPublic) === -1) {
$(burnAfterReading).remove();
return;
}
// When the burn after reading option is selected, transform the modal buttons
$(burnAfterReading).css({
display: 'flex'
});
});
var $rights = $(rights);
var saveValue = function () {
var edit = Util.isChecked($rights.find('#cp-share-editable-true'));
var present = Util.isChecked($rights.find('#cp-share-present'));
common.setAttribute(['general', 'share'], {
edit: edit,
present: present
});
};
var burnAfterReadingUrl;
var getLinkValue = function (initValue, cb) {
var val = initValue || {};
var edit = val.edit !== undefined ? val.edit : Util.isChecked($rights.find('#cp-share-editable-true'));
var embed = val.embed;
var present = val.present !== undefined ? val.present : Util.isChecked($rights.find('#cp-share-present'));
var burnAfterReading = Util.isChecked($rights.find('#cp-share-bar'));
if (burnAfterReading && !burnAfterReadingUrl) {
if (cb) { // Called from the contacts tab, "share" button
var barHref = origin + pathname + '#' + (hashes.viewHash || hashes.editHash);
return makeBurnAfterReadingUrl(common, barHref, channel, function (url) {
cb(url);
});
}
return Messages.burnAfterReading_generateLink;
}
var hash = (!hashes.viewHash || (edit && hashes.editHash)) ? hashes.editHash : hashes.viewHash;
var href = burnAfterReading ? burnAfterReadingUrl : (origin + pathname + '#' + hash);
var parsed = Hash.parsePadUrl(href);
return origin + parsed.getUrl({embed: embed, present: present});
};
var makeCancelButton = function() {
return {
className: 'cancel',
name: Messages.cancel,
onClick: function () {},
keys: [27]
};
};
// Share link tab
var linkContent = config.sharedFolder ? [
h('label', Messages.sharedFolders_share),
h('br'),
] : [
UI.createCheckbox('cp-share-embed', Messages.share_linkEmbed, false, { mark: {tabindex:1} }),
];
linkContent.push(h('div.cp-spacer'));
linkContent.push(UI.dialog.selectableArea('', { id: 'cp-share-link-preview', tabindex: 1, rows:3}));
// Show alert if the pad is password protected
if (hasPassword) {
linkContent.push(h('div.alert.alert-primary', [
h('i.fa.fa-lock'),
Messages.share_linkPasswordAlert, h('br'),
makeFaqLink()
]));
}
// warning about sharing links
var localStore = window.cryptpadStore;
var dismissButton = h('span.fa.fa-times');
var shareLinkWarning = h('div.alert.alert-warning.dismissable',
{ style: 'display: none;' },
[
h('span.cp-inline-alert-text', Messages.share_linkWarning),
dismissButton
]);
linkContent.push(shareLinkWarning);
localStore.get('hide-alert-shareLinkWarning', function (val) {
if (val === '1') { return; }
$(shareLinkWarning).show();
$(dismissButton).on('click', function () {
localStore.put('hide-alert-shareLinkWarning', '1');
$(shareLinkWarning).remove();
});
});
linkContent.push($(barAlert).clone()[0]); // Burn after reading
var link = h('div.cp-share-modal', linkContent);
var $link = $(link);
var linkButtons = [
makeCancelButton(),
!config.sharedFolder && {
className: 'secondary cp-nobar',
name: Messages.share_linkOpen,
onClick: function () {
saveValue();
var v = getLinkValue({
embed: Util.isChecked($link.find('#cp-share-embed'))
});
window.open(v);
return true;
},
keys: [[13, 'ctrl']]
}, {
className: 'primary cp-nobar',
name: Messages.share_linkCopy,
onClick: function () {
saveValue();
var v = getLinkValue({
embed: Util.isChecked($link.find('#cp-share-embed'))
});
var success = Clipboard.copy(v);
if (success) { UI.log(Messages.shareSuccess); }
},
keys: [13]
}, {
className: 'primary cp-bar',
name: 'GENERATE LINK',
onClick: function () {
var barHref = origin + pathname + '#' + (hashes.viewHash || hashes.editHash);
makeBurnAfterReadingUrl(common, barHref, channel, function (url) {
burnAfterReadingUrl = url;
$rights.find('input[type="radio"]').trigger('change');
});
return true;
},
keys: []
}
];
var frameLink = UI.dialog.customModal(link, {
buttons: linkButtons,
onClose: config.onClose,
});
$(frameLink).find('.cp-bar').hide();
// Share with contacts tab
var teams = getEditableTeams(common, config);
config.teams = teams;
var hasFriends = Object.keys(config.friends || {}).length ||
Object.keys(teams).length;
var onFriendShare = Util.mkEvent();
var friendsObject = hasFriends ? createShareWithFriends(config, onFriendShare, getLinkValue) : noContactsMessage(common);
var friendsList = friendsObject.content;
onFriendShare.reg(saveValue);
var contactsContent = h('div.cp-share-modal');
var $contactsContent = $(contactsContent);
$contactsContent.append(friendsList);
// Show alert if the pad is password protected
if (hasPassword) {
$contactsContent.append(h('div.alert.alert-primary', [
h('i.fa.fa-unlock'),
Messages.share_contactPasswordAlert, h('br'),
makeFaqLink()
]));
}
$(contactsContent).append($(barAlert).clone()); // Burn after reading
var contactButtons = friendsObject.buttons;
contactButtons.unshift(makeCancelButton());
var onShowContacts = function () {
if (!hasFriends) {
$rights.hide();
}
};
var frameContacts = UI.dialog.customModal(contactsContent, {
buttons: contactButtons,
onClose: config.onClose,
});
// Embed tab
var getEmbedValue = function () {
var url = getLinkValue({
embed: true
});
return '<iframe src="' + url + '"></iframe>';
};
var embedContent = [
h('p', Messages.viewEmbedTag),
UI.dialog.selectableArea(getEmbedValue(), { id: 'cp-embed-link-preview', tabindex: 1, rows: 3})
];
// Show alert if the pad is password protected
if (hasPassword) {
embedContent.push(h('div.alert.alert-primary', [
h('i.fa.fa-lock'), ' ',
Messages.share_embedPasswordAlert, h('br'),
makeFaqLink()
]));
}
var embedButtons = [
makeCancelButton(), {
className: 'primary',
name: Messages.share_linkCopy,
onClick: function () {
var v = getEmbedValue();
var success = Clipboard.copy(v);
if (success) { UI.log(Messages.shareSuccess); }
},
keys: [13]
}];
var onShowEmbed = function () {
$rights.find('#cp-share-bar').closest('label').hide();
$rights.find('input[type="radio"]:enabled').first().prop('checked', 'checked');
$rights.find('input[type="radio"]').trigger('change');
};
var embed = h('div.cp-share-modal', embedContent);
var $embed = $(embed);
var frameEmbed = UI.dialog.customModal(embed, {
buttons: embedButtons,
onClose: config.onClose,
});
// update values for link and embed preview when radio btns change
$embed.find('#cp-embed-link-preview').val(getEmbedValue());
$link.find('#cp-share-link-preview').val(getLinkValue());
$rights.find('input[type="radio"]').on('change', function () {
$link.find('#cp-share-link-preview').val(getLinkValue({
embed: Util.isChecked($link.find('#cp-share-embed'))
}));
// Hide or show the burn after reading alert
if (Util.isChecked($rights.find('#cp-share-bar')) && !burnAfterReadingUrl) {
$('.cp-alertify-bar-selected').show();
// Show burn after reading button
$('.alertify').find('.cp-bar').show();
$('.alertify').find('.cp-nobar').hide();
return;
}
$embed.find('#cp-embed-link-preview').val(getEmbedValue());
// Hide burn after reading button
$('.alertify').find('.cp-nobar').show();
$('.alertify').find('.cp-bar').hide();
$('.cp-alertify-bar-selected').hide();
});
$link.find('input[type="checkbox"]').on('change', function () {
$link.find('#cp-share-link-preview').val(getLinkValue({
embed: Util.isChecked($link.find('#cp-share-embed'))
}));
});
// Create modal
var resetTab = function () {
$rights.show();
$rights.find('label.cp-radio').show();
};
var tabs = [{
title: Messages.share_contactCategory,
icon: "fa fa-address-book",
content: frameContacts,
active: hasFriends,
onShow: onShowContacts,
onHide: resetTab
}, {
title: Messages.share_linkCategory,
icon: "fa fa-link",
content: frameLink,
active: !hasFriends
}, {
title: Messages.share_embedCategory,
icon: "fa fa-code",
content: frameEmbed,
onShow: onShowEmbed,
onHide: resetTab
}];
if (typeof(AppConfig.customizeShareOptions) === 'function') {
AppConfig.customizeShareOptions(hashes, tabs, {
type: 'DEFAULT',
origin: origin,
pathname: pathname
});
}
var modal = UI.dialog.tabs(tabs);
$(modal).find('.alertify-tabs-titles').after(rights);
// disable edit share options if you don't have edit rights
if (!hashes.editHash) {
$rights.find('#cp-share-editable-false').attr('checked', true);
$rights.find('#cp-share-editable-true').removeAttr('checked').attr('disabled', true);
} else if (!hashes.viewHash) {
$rights.find('#cp-share-editable-false').removeAttr('checked').attr('disabled', true);
$rights.find('#cp-share-present').removeAttr('checked').attr('disabled', true);
$rights.find('#cp-share-editable-true').attr('checked', true);
}
common.getAttribute(['general', 'share'], function (err, val) {
val = val || {};
if (val.present && canPresent) {
$rights.find('#cp-share-editable-false').prop('checked', false);
$rights.find('#cp-share-editable-true').prop('checked', false);
$rights.find('#cp-share-present').prop('checked', true);
} else if ((val.edit === false && hashes.viewHash) || !hashes.editHash) {
$rights.find('#cp-share-editable-false').prop('checked', true);
$rights.find('#cp-share-editable-true').prop('checked', false);
$rights.find('#cp-share-present').prop('checked', false);
} else {
$rights.find('#cp-share-editable-true').prop('checked', true);
$rights.find('#cp-share-editable-false').prop('checked', false);
$rights.find('#cp-share-present').prop('checked', false);
}
delete val.embed;
if (!canPresent) {
delete val.present;
}
$link.find('#cp-share-link-preview').val(getLinkValue(val));
});
common.getMetadataMgr().onChange(function () {
// "hashes" is only available is the secure "share" app
var _hashes = common.getMetadataMgr().getPrivateData().hashes;
if (!_hashes) { return; }
hashes = _hashes;
$link.find('#cp-share-link-preview').val(getLinkValue());
});
return modal;
};
UIElements.createFileShareModal = function (config) {
var origin = config.origin;
var pathname = config.pathname;
var hashes = config.hashes;
var common = config.common;
var fileData = config.fileData;
if (!hashes.fileHash) { throw new Error("You must provide a file hash"); }
var url = origin + pathname + '#' + hashes.fileHash;
// check if the file is password protected
var parsedHref = Hash.parsePadUrl(url);
var hasPassword = parsedHref.hashData.password;
var makeFaqLink = function () {
var link = h('span', [
h('i.fa.fa-question-circle'),
h('a', {href: '#'}, Messages.passwordFaqLink)
]);
$(link).click(function () {
common.openURL(config.origin + "/faq.html#security-pad_password");
});
return link;
};
var getLinkValue = function () { return url; };
var makeCancelButton = function() {
return {className: 'cancel',
name: Messages.cancel,
onClick: function () {},
keys: [27]};
};
// Share link tab
var linkContent = [
UI.dialog.selectableArea(getLinkValue(), { id: 'cp-share-link-preview', tabindex: 1, rows:2 })
];
// Show alert if the pad is password protected
if (hasPassword) {
linkContent.push(h('div.alert.alert-primary', [
h('i.fa.fa-lock'),
Messages.share_linkPasswordAlert, h('br'),
makeFaqLink()
]));
}
// warning about sharing links
var localStore = window.cryptpadStore;
var dismissButton = h('span.fa.fa-times');
var shareLinkWarning = h('div.alert.alert-warning.dismissable',
{ style: 'display: none;' },
[
h('span.cp-inline-alert-text', Messages.share_linkWarning),
dismissButton
]);
linkContent.push(shareLinkWarning);
localStore.get('hide-alert-shareLinkWarning', function (val) {
if (val === '1') { return; }
$(shareLinkWarning).show();
$(dismissButton).on('click', function () {
localStore.put('hide-alert-shareLinkWarning', '1');
$(shareLinkWarning).remove();
});
});
var link = h('div.cp-share-modal', linkContent);
var linkButtons = [
makeCancelButton(),
{
className: 'primary',
name: Messages.share_linkCopy,
onClick: function () {
var v = getLinkValue();
var success = Clipboard.copy(v);
if (success) { UI.log(Messages.shareSuccess);
}
},
keys: [13]
}
];
var frameLink = UI.dialog.customModal(link, {
buttons: linkButtons,
onClose: config.onClose,
});
// share with contacts tab
var teams = getEditableTeams(common, config);
config.teams = teams;
var hasFriends = Object.keys(config.friends || {}).length ||
Object.keys(teams).length;
var friendsObject = hasFriends ? createShareWithFriends(config, null, getLinkValue) : noContactsMessage(common);
var friendsList = friendsObject.content;
var contactsContent = h('div.cp-share-modal');
var $contactsContent = $(contactsContent);
$contactsContent.append(friendsList);
// Show alert if the pad is password protected
if (hasPassword) {
$contactsContent.append(h('div.alert.alert-primary', [
h('i.fa.fa-unlock'),
Messages.share_contactPasswordAlert, h('br'),
makeFaqLink()
]));
}
var contactButtons = friendsObject.buttons;
contactButtons.unshift(makeCancelButton());
var frameContacts = UI.dialog.customModal(contactsContent, {
buttons: contactButtons,
onClose: config.onClose,
});
// Embed tab
var embed = h('div.cp-share-modal', [
h('p', Messages.fileEmbedScript),
UI.dialog.selectable(common.getMediatagScript()),
h('p', Messages.fileEmbedTag),
UI.dialog.selectable(common.getMediatagFromHref(fileData)),
]);
// Show alert if the pad is password protected
if (hasPassword) {
embed.append(h('div.alert.alert-primary', [
h('i.fa.fa-lock'), ' ',
Messages.share_embedPasswordAlert, h('br'),
makeFaqLink()
]));
}
var embedButtons = [{
className: 'cancel',
name: Messages.cancel,
onClick: function () {},
keys: [27]
}, {
className: 'primary',
name: Messages.share_mediatagCopy,
onClick: function () {
var v = common.getMediatagFromHref(fileData);
var success = Clipboard.copy(v);
if (success) { UI.log(Messages.shareSuccess); }
},
keys: [13]
}];
var frameEmbed = UI.dialog.customModal(embed, {
buttons: embedButtons,
onClose: config.onClose,
});
// Create modal
var tabs = [{
title: Messages.share_contactCategory,
icon: "fa fa-address-book",
content: frameContacts,
active: hasFriends,
}, {
title: Messages.share_linkCategory,
icon: "fa fa-link",
content: frameLink,
active: !hasFriends
}, {
title: Messages.share_embedCategory,
icon: "fa fa-code",
content: frameEmbed
}];
if (typeof(AppConfig.customizeShareOptions) === 'function') {
AppConfig.customizeShareOptions(hashes, tabs, {
type: 'FILE',
origin: origin,
pathname: pathname
});
}
var modal = UI.dialog.tabs(tabs);
return modal;
};
UIElements.createInviteTeamModal = function (config) {
var common = config.common;
var hasFriends = Object.keys(config.friends || {}).length !== 0;
@ -1159,7 +336,7 @@ define([
buttons: contactsButtons
};
};
var friendsObject = hasFriends ? getContacts() : noContactsMessage(common);
var friendsObject = hasFriends ? getContacts() : UIElements.noContactsMessage(common);
var friendsList = friendsObject.content;
var contactsButtons = friendsObject.buttons;
contactsButtons.unshift({
@ -1241,7 +418,7 @@ define([
var localStore = window.cryptpadStore;
localStore.get('hide-alert-teamInvite', function (val) {
if (val === '1') { return; }
$(linkWarning).show();
$(linkWarning).css('display', 'flex');
$(dismissButton).on('click', function () {
localStore.put('hide-alert-teamInvite', '1');
@ -2104,6 +1281,9 @@ define([
cb(null, $container);
return {
$container: $container,
update: function () {
common.getPinUsage(teamId, todo);
},
stop: function () {
clearInterval(interval);
}

View File

@ -7,14 +7,15 @@ define([
'/common/hyperscript.js',
'/common/inner/common-mediatag.js',
'/common/media-tag.js',
'/common/highlight/highlight.pack.js',
'/customize/messages.js',
'/common/highlight/highlight.pack.js',
'/bower_components/diff-dom/diffDOM.js',
'/bower_components/tweetnacl/nacl-fast.min.js',
'css!/common/highlight/styles/github.css'
],function ($, ApiConfig, Marked, Hash, Util, h, MT, MediaTag, Highlight, Messages) {
],function ($, ApiConfig, Marked, Hash, Util, h, MT, MediaTag, Messages) {
var DiffMd = {};
var Highlight = window.hljs;
var DiffDOM = window.diffDOM;
var renderer = new Marked.Renderer();
var restrictedRenderer = new Marked.Renderer();

View File

@ -1,5 +1,6 @@
define([
'jquery',
'/api/config',
'/common/toolbar.js',
'json.sortify',
'/common/common-util.js',
@ -9,6 +10,7 @@ define([
'/common/common-constants.js',
'/common/common-feedback.js',
'/common/inner/share.js',
'/common/inner/access.js',
'/common/inner/properties.js',
@ -19,6 +21,7 @@ define([
'/customize/messages.js',
], function (
$,
ApiConfig,
Toolbar,
JSONSortify,
Util,
@ -27,6 +30,7 @@ define([
UI,
Constants,
Feedback,
Share,
Access,
Properties,
nThen,
@ -149,6 +153,17 @@ define([
var localStore = window.cryptpadStore;
APP.store = {};
$(window).keydown(function (e) {
if (e.which === 70 && e.ctrlKey) {
e.preventDefault();
e.stopPropagation();
if (APP.displayDirectory) {
APP.displayDirectory([SEARCH]);
}
return;
}
});
var makeLS = function (teamId) {
var suffix = teamId ? ('-' + teamId) : '';
var LS_LAST = "app-drive-lastOpened" + suffix;
@ -1374,7 +1389,7 @@ define([
}
$button.show();
$button.css({
background: '#000'
background: '#63b1f7'
});
window.setTimeout(function () {
$button.css({
@ -2007,26 +2022,25 @@ define([
if (!parsed.hash && !roParsed.hash) { return void console.error("Invalid href: "+(data.href || data.roHref)); }
var friends = common.getFriends();
var ro = folders[id] && folders[id].version >= 2;
var modal = UIElements.createShareModal({
teamId: APP.team,
origin: APP.origin,
pathname: "/drive/",
friends: friends,
title: data.title,
password: data.password,
sharedFolder: true,
common: common,
hashes: {
editHash: parsed.hash,
viewHash: ro && roParsed.hash,
}
});
// If we're a viewer and this is an old shared folder (no read-only mode), we
// can't share the read-only URL and we don't have access to the edit one.
// We should hide the share button.
if (!modal) { return; }
if (!data.href && !ro) { return; }
$shareBlock.click(function () {
UI.openCustomModal(modal);
Share.getShareModal(common, {
teamId: APP.team,
origin: APP.origin,
pathname: "/drive/",
friends: friends,
title: data.title,
password: data.password,
sharedFolder: true,
common: common,
hashes: {
editHash: parsed.hash,
viewHash: ro && roParsed.hash,
}
});
});
$container.append($shareBlock);
return $shareBlock;
@ -2340,7 +2354,7 @@ define([
return $(common.fixLinks($box.html(msg)));
}
if (!APP.loggedIn) {
msg = APP.newSharedFolder ? Messages.fm_info_sharedFolder : Messages.fm_info_anonymous;
msg = APP.newSharedFolder ? Messages.fm_info_sharedFolder : Messages._getKey('fm_info_anonymous', [ApiConfig.inactiveTime || 90]);
return $(common.fixLinks($box.html(msg)));
}
if (!msg || APP.store['hide-info-' + path[0]] === '1') {
@ -3660,14 +3674,6 @@ define([
if (!readOnlyFolder) {
createNewButton(isInRoot, APP.toolbar.$bottomL);
}
/*
// The share button is not displayed anymore in the toolbar: users can't know
// if they're going to share the current shared folder or the selected pad
if (sfId) {
createShareButton(sfId, APP.toolbar.$bottomL);
}
*/
if (APP.mobile()) {
var $context = $('<button>', {
@ -3687,6 +3693,9 @@ define([
APP.hideMenu();
return;
}
if (!$li.length) {
return void $dirContent.contextmenu();
}
// Open the menu
$li.contextmenu();
});
@ -4334,7 +4343,7 @@ define([
else if ($this.hasClass('cp-app-drive-context-share')) {
if (paths.length !== 1) { return; }
el = manager.find(paths[0].path);
var parsed, modal;
var parsed;
var friends = common.getFriends();
var anonDrive = manager.isPathIn(currentPath, [FILES_DATA]) && !APP.loggedIn;
@ -4406,9 +4415,10 @@ define([
sharedFolder: sf,
common: common
};
modal = padType === 'file' ? UIElements.createFileShareModal(padData)
: UIElements.createShareModal(padData);
UI.openCustomModal(modal);
if (padType === 'file') {
return void Share.getFileShareModal(common, padData);
}
Share.getShareModal(common, padData);
}
}
else if ($this.hasClass('cp-app-drive-context-savelocal')) {
@ -4780,7 +4790,7 @@ define([
placeholder: Messages.settings_changePasswordNew,
style: 'flex: 1;'
});
var passwordOk = h('button.btn', Messages.properties_changePasswordButton);
var passwordOk = h('button.btn.btn-secondary', Messages.properties_changePasswordButton);
var changePass = h('span.cp-password-container', [
newPassword,
passwordOk

File diff suppressed because one or more lines are too long

View File

@ -33,7 +33,7 @@ define([
opts = opts || {};
var redrawAll = function () {};
var addBtn = h('button.btn.btn-primary.fa.fa-arrow-left');
var addBtn = h('button.btn.btn-primary.cp-access-add', [h('i.fa.fa-arrow-left'), h('i.fa.fa-arrow-up')]);
var div1 = h('div.cp-share-column.cp-ownership');
var divMid = h('div.cp-share-column-mid', addBtn);
@ -152,7 +152,8 @@ define([
var $div = $(h('div.cp-share-column'));
var _friends = Util.clone(friends);
Object.keys(_friends).forEach(function (curve) {
var friendKeys = Object.keys(_friends);
friendKeys.forEach(function (curve) {
if (owners.indexOf(_friends[curve].edPublic) !== -1 ||
pending_owners.indexOf(_friends[curve].edPublic) !== -1 ||
!_friends[curve].notifications) {
@ -160,10 +161,21 @@ define([
}
});
if (!Object.keys(_friends).length) {
var friendText;
if (!friendKeys.length) {
console.error(UIElements.noContactsMessage(common));
var findContacts = UIElements.noContactsMessage(common);
friendText = h('span.cp-app-prop-content',
findContacts.content
);
} else {
friendText = h('span.cp-app-prop-content', Messages.access_noContact);
}
$div.append(h('div.cp-app-prop', [
Messages.contacts,
h('br'),
h('span.cp-app-prop-content', Messages.access_noContact)
friendText
]));
} else {
var addCol = UIElements.getUserGrid(Messages.contacts, {
@ -388,7 +400,7 @@ define([
var redrawAll = function () {};
var addBtn = h('button.btn.btn-primary.fa.fa-arrow-left');
var addBtn = h('button.btn.btn-primary.cp-access-add', [h('i.fa.fa-arrow-left'), h('i.fa.fa-arrow-up')]);
var div1 = h('div.cp-share-column.cp-allowlist');
var divMid = h('div.cp-share-column-mid.cp-overlay-container', [
@ -528,7 +540,7 @@ define([
]);
};
// Add owners column
// Add allow list column
var drawAdd = function () {
var priv = metadataMgr.getPrivateData();
var teamsData = Util.tryParse(JSON.stringify(priv.teams)) || {};
@ -538,17 +550,28 @@ define([
$div.addClass('cp-overlay-container').append(h('div.cp-overlay'));
var _friends = Util.clone(friends);
Object.keys(_friends).forEach(function (curve) {
var friendKeys = Object.keys(_friends);
friendKeys.forEach(function (curve) {
if (owners.indexOf(_friends[curve].edPublic) !== -1 ||
allowed.indexOf(_friends[curve].edPublic) !== -1) {
delete _friends[curve];
}
});
if (!Object.keys(_friends).length) {
var friendText;
if (!friendKeys.length) {
var findContacts = UIElements.noContactsMessage(common);
friendText = h('span.cp-app-prop-content',
findContacts.content
);
} else {
friendText = h('span.cp-app-prop-content', Messages.access_noContact);
}
$div.append(h('div.cp-app-prop', [
Messages.contacts,
h('br'),
h('span.cp-app-prop-content', Messages.access_noContact)
friendText
]));
} else {
var addCol = UIElements.getUserGrid(Messages.contacts, {
@ -1048,6 +1071,16 @@ define([
opts = opts || {};
opts.wide = true;
opts.access = true;
var hasFriends = Object.keys(common.getFriends()).length;
var buttons = hasFriends? []: UIElements.noContactsMessage(common).buttons;
buttons.unshift({
className: 'cancel',
name: Messages.filePicker_close,
onClick: function () {},
keys: [27],
});
var tabs = [{
getTab: getAccessTab,
title: Messages.access_main,
@ -1056,10 +1089,12 @@ define([
getTab: getAllowTab,
title: Messages.access_allow,
icon: "fa fa-list",
buttons: buttons,
}, {
getTab: getOwnersTab,
title: Messages.creation_owners,
icon: "fa fa-id-badge",
buttons: buttons,
}];
Modal.getModal(common, opts, tabs, cb);
};

View File

@ -110,6 +110,10 @@ define([
waitFor.abort();
return void cb(e);
}
if (c && c.content && c.buttons) {
obj.buttons = c.buttons;
c = c.content;
}
var node = (c instanceof $) ? c[0] : c;
tabs[i] = {
content: c && UI.dialog.customModal(node, {
@ -120,6 +124,9 @@ define([
}
}),
disabled: !c,
active: obj.active,
onShow: obj.onShow,
onHide: obj.onHide,
title: obj.title,
icon: obj.icon
};

855
www/common/inner/share.js Normal file
View File

@ -0,0 +1,855 @@
define([
'jquery',
'/common/common-util.js',
'/common/common-hash.js',
'/common/common-interface.js',
'/common/common-ui-elements.js',
'/common/inner/common-modal.js',
'/common/hyperscript.js',
'/common/clipboard.js',
'/customize/messages.js',
'/bower_components/nthen/index.js',
], function ($, Util, Hash, UI, UIElements, Modal, h, Clipboard,
Messages, nThen) {
var Share = {};
var createShareWithFriends = function (config, onShare, linkGetter) {
var common = config.common;
var sframeChan = common.getSframeChannel();
var title = config.title;
var friends = config.friends || {};
var teams = config.teams || {};
var myName = common.getMetadataMgr().getUserData().name;
var order = [];
var smallCurves = Object.keys(friends).map(function (c) {
return friends[c].curvePublic.slice(0,8);
});
var div = h('div.contains-nav');
var $div = $(div);
// Replace "copy link" by "share with friends" if at least one friend is selected
// Also create the "share with friends" button if it doesn't exist
var refreshButtons = function () {
var $nav = $div.closest('.alertify').find('nav');
var friendMode = $div.find('.cp-usergrid-user.cp-selected').length;
if (friendMode) {
$nav.find('button.cp-share-with-friends').prop('disabled', '');
} else {
$nav.find('button.cp-share-with-friends').prop('disabled', 'disabled');
}
};
config.noInclude = true;
Object.keys(friends).forEach(function (curve) {
var data = friends[curve];
if (curve.length > 40 && data.notifications) { return; }
delete friends[curve];
});
var others = [];
if (Object.keys(friends).length) {
var friendsList = UIElements.getUserGrid(Messages.share_linkFriends, {
common: common,
data: friends,
noFilter: false,
large: true
}, refreshButtons);
var friendDiv = friendsList.div;
$div.append(friendDiv);
others = friendsList.icons;
}
if (Object.keys(teams).length) {
var teamsList = UIElements.getUserGrid(Messages.share_linkTeam, {
common: common,
noFilter: true,
large: true,
data: teams
}, refreshButtons);
$div.append(teamsList.div);
}
var shareButton = {
className: 'primary cp-share-with-friends',
name: Messages.share_withFriends,
onClick: function () {
var href;
nThen(function (waitFor) {
var w = waitFor();
// linkGetter can be async if this is a burn after reading URL
var res = linkGetter({}, function (url) {
if (!url) {
waitFor.abort();
return;
}
href = url;
setTimeout(w);
});
if (res && /^http/.test(res)) {
href = Hash.getRelativeHref(res);
setTimeout(w);
return;
}
}).nThen(function () {
var $friends = $div.find('.cp-usergrid-user.cp-selected');
$friends.each(function (i, el) {
var curve = $(el).attr('data-curve');
var ed = $(el).attr('data-ed');
var friend = curve && friends[curve];
var team = teams[ed];
// If the selected element is a friend or a team without edit right,
// send a notification
var mailbox = friend || ((team && team.viewer) ? team : undefined);
if (mailbox) { // Friend
if (friends[curve] && !mailbox.notifications) { return; }
if (mailbox.notifications && mailbox.curvePublic) {
common.mailbox.sendTo("SHARE_PAD", {
href: href,
password: config.password,
isTemplate: config.isTemplate,
name: myName,
title: title
}, {
viewed: team && team.id,
channel: mailbox.notifications,
curvePublic: mailbox.curvePublic
});
return;
}
}
// If it's a team with edit right, add the pad directly
if (!team) { return; }
sframeChan.query('Q_STORE_IN_TEAM', {
href: href,
password: config.password,
path: config.isTemplate ? ['template'] : undefined,
title: title,
teamId: team.id
}, function (err) {
if (err) { return void console.error(err); }
});
});
UI.findCancelButton().click();
// Update the "recently shared with" array:
// Get the selected curves
var curves = $friends.toArray().map(function (el) {
return ($(el).attr('data-curve') || '').slice(0,8);
}).filter(function (x) { return x; });
// Prepend them to the "order" array
Array.prototype.unshift.apply(order, curves);
order = Util.deduplicateString(order);
// Make sure we don't have "old" friends and save
order = order.filter(function (curve) {
return smallCurves.indexOf(curve) !== -1;
});
common.setAttribute(['general', 'share-friends'], order);
if (onShare) {
onShare.fire();
}
});
},
keys: [13]
};
common.getAttribute(['general', 'share-friends'], function (err, val) {
order = val || [];
// Sort friends by "recently shared with"
others.sort(function (a, b) {
var ca = ($(a).attr('data-curve') || '').slice(0,8);
var cb = ($(b).attr('data-curve') || '').slice(0,8);
if (!ca && !cb) { return 0; }
if (!ca) { return 1; }
if (!cb) { return -1; }
var ia = order.indexOf(ca);
var ib = order.indexOf(cb);
if (ia === -1 && ib === -1) { return 0; }
if (ia === -1) { return 1; }
if (ib === -1) { return -1; }
return ia - ib;
});
// Reorder the friend icons
others.forEach(function (el, i) {
$(el).attr('data-order', i).css('order', i);
});
// Display them
$(friendDiv).find('.cp-usergrid-grid').detach();
$(friendDiv).append(h('div.cp-usergrid-grid', others));
refreshButtons();
});
return {
content: div,
buttons: [shareButton]
};
};
var getEditableTeams = function (common, config) {
var privateData = common.getMetadataMgr().getPrivateData();
var teamsData = Util.tryParse(JSON.stringify(privateData.teams)) || {};
var teams = {};
Object.keys(teamsData).forEach(function (id) {
// config.teamId only exists when we're trying to share a pad from a team drive
// In this case, we don't want to share the pad with the current team
if (config.teamId && config.teamId === id) { return; }
var t = teamsData[id];
teams[t.edPublic] = {
viewer: !teamsData[id].hasSecondaryKey,
notifications: t.notifications,
curvePublic: t.curvePublic,
displayName: t.name,
edPublic: t.edPublic,
avatar: t.avatar,
id: id
};
});
return teams;
};
var makeBurnAfterReadingUrl = function (common, href, channel, cb) {
var keyPair = Hash.generateSignPair();
var parsed = Hash.parsePadUrl(href);
var newHref = parsed.getUrl({
ownerKey: keyPair.safeSignKey
});
var sframeChan = common.getSframeChannel();
var rtChannel;
nThen(function (waitFor) {
if (parsed.type !== "sheet") { return; }
common.getPadAttribute('rtChannel', waitFor(function (err, chan) {
rtChannel = chan;
}));
}).nThen(function (waitFor) {
sframeChan.query('Q_SET_PAD_METADATA', {
channel: channel,
command: 'ADD_OWNERS',
value: [keyPair.validateKey]
}, waitFor(function (err) {
if (err) {
waitFor.abort();
UI.warn(Messages.error);
}
}));
if (rtChannel) {
sframeChan.query('Q_SET_PAD_METADATA', {
channel: rtChannel,
command: 'ADD_OWNERS',
value: [keyPair.validateKey]
}, waitFor(function (err) {
if (err) { console.error(err); }
}));
}
}).nThen(function () {
cb(newHref);
});
};
var makeFaqLink = function (opts) {
var link = h('span', [
h('i.fa.fa-question-circle'),
h('a', {href: '#'}, Messages.passwordFaqLink)
]);
$(link).click(function () {
opts.common.openURL(opts.origin + "/faq.html#security-pad_password");
});
return link;
};
var makeCancelButton = function() {
return {
className: 'cancel',
name: Messages.cancel,
onClick: function () {},
keys: [27]
};
};
var getContactsTab = function (Env, data, opts, _cb) {
var cb = Util.once(Util.mkAsync(_cb));
var common = Env.common;
var hasFriends = opts.hasFriends;
var onFriendShare = Util.mkEvent();
var friendsObject = hasFriends ? createShareWithFriends(opts, onFriendShare, opts.getLinkValue) : UIElements.noContactsMessage(common);
var friendsList = friendsObject.content;
onFriendShare.reg(opts.saveValue);
var contactsContent = h('div.cp-share-modal');
var $contactsContent = $(contactsContent);
$contactsContent.append(friendsList);
// Show alert if the pad is password protected
if (opts.hasPassword) {
$contactsContent.append(h('div.alert.alert-primary', [
h('i.fa.fa-unlock'),
Messages.share_contactPasswordAlert, h('br'),
makeFaqLink(opts)
]));
}
// Burn after reading warning
if (opts.barAlert) { $contactsContent.append(opts.barAlert.cloneNode(true)); }
var contactButtons = friendsObject.buttons;
contactButtons.unshift(makeCancelButton());
cb(void 0, {
content: contactsContent,
buttons: contactButtons
});
};
var getLinkTab = function (Env, data, opts, _cb) {
var cb = Util.once(Util.mkAsync(_cb));
var common = Env.common;
var origin = opts.origin;
var pathname = opts.pathname;
var hashes = opts.hashes;
// Create modal
var linkContent = opts.sharedFolder ? [
h('label', Messages.sharedFolders_share),
h('br'),
] : [
UI.createCheckbox('cp-share-embed', Messages.share_linkEmbed, false, { mark: {tabindex:1} }),
];
linkContent.push(h('div.cp-spacer'));
linkContent.push(UI.dialog.selectableArea('', { id: 'cp-share-link-preview', tabindex: 1, rows:3}));
// Show alert if the pad is password protected
if (opts.hasPassword) {
linkContent.push(h('div.alert.alert-primary', [
h('i.fa.fa-lock'),
Messages.share_linkPasswordAlert, h('br'),
makeFaqLink(opts)
]));
}
// warning about sharing links
var localStore = window.cryptpadStore;
var dismissButton = h('span.fa.fa-times');
var shareLinkWarning = h('div.alert.alert-warning.dismissable',
{ style: 'display: none;' },
[
h('span.cp-inline-alert-text', Messages.share_linkWarning),
dismissButton
]);
linkContent.push(shareLinkWarning);
localStore.get('hide-alert-shareLinkWarning', function (val) {
if (val === '1') { return; }
$(shareLinkWarning).css('display', 'flex');
$(dismissButton).on('click', function () {
localStore.put('hide-alert-shareLinkWarning', '1');
$(shareLinkWarning).remove();
});
});
// Burn after reading
if (opts.barAlert) { linkContent.push(opts.barAlert.cloneNode(true)); }
var link = h('div.cp-share-modal', linkContent);
var $link = $(link);
$link.find('#cp-share-link-preview').val(opts.getLinkValue());
$link.find('input[type="checkbox"]').on('change', function () {
$link.find('#cp-share-link-preview').val(opts.getLinkValue({
embed: Util.isChecked($link.find('#cp-share-embed'))
}));
});
//Messages.share_bar = "Generate link"; // XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
Messages.share_bar = Messages.team_inviteLinkCreate; // XXX
var linkButtons = [
makeCancelButton(),
!opts.sharedFolder && {
className: 'secondary cp-nobar',
name: Messages.share_linkOpen,
onClick: function () {
opts.saveValue();
var v = opts.getLinkValue({
embed: Util.isChecked($link.find('#cp-share-embed'))
});
window.open(v);
return true;
},
keys: [[13, 'ctrl']]
}, {
className: 'primary cp-nobar',
name: Messages.share_linkCopy,
onClick: function () {
opts.saveValue();
var v = opts.getLinkValue({
embed: Util.isChecked($link.find('#cp-share-embed'))
});
var success = Clipboard.copy(v);
if (success) { UI.log(Messages.shareSuccess); }
},
keys: [13]
}, {
className: 'primary cp-bar',
name: Messages.share_bar,
onClick: function () {
var barHref = origin + pathname + '#' + (hashes.viewHash || hashes.editHash);
makeBurnAfterReadingUrl(common, barHref, opts.channel, function (url) {
opts.burnAfterReadingUrl = url;
opts.$rights.find('input[type="radio"]').trigger('change');
});
return true;
},
keys: []
}
];
$link.find('.cp-bar').hide();
cb(void 0, {
content: link,
buttons: linkButtons
});
};
var getEmbedTab = function (Env, data, opts, _cb) {
var cb = Util.once(Util.mkAsync(_cb));
var embedContent = [
h('p', Messages.viewEmbedTag),
UI.dialog.selectableArea(opts.getEmbedValue(), { id: 'cp-embed-link-preview', tabindex: 1, rows: 3})
];
// Show alert if the pad is password protected
if (opts.hasPassword) {
embedContent.push(h('div.alert.alert-primary', [
h('i.fa.fa-lock'), ' ',
Messages.share_embedPasswordAlert, h('br'),
makeFaqLink(opts)
]));
}
var embedButtons = [
makeCancelButton(),
{
className: 'primary',
name: Messages.share_linkCopy,
onClick: function () {
var v = opts.getEmbedValue();
var success = Clipboard.copy(v);
if (success) { UI.log(Messages.shareSuccess); }
},
keys: [13]
}];
var embed = h('div.cp-share-modal', embedContent);
var $embed = $(embed);
$embed.find('#cp-embed-link-preview').val(opts.getEmbedValue());
cb(void 0, {
content: embed,
buttons: embedButtons
});
};
var getRightsHeader = function (common, opts) {
var hashes = opts.hashes;
var hash = hashes.editHash || hashes.viewHash;
var origin = opts.origin;
var pathname = opts.pathname;
var parsed = Hash.parsePadUrl(pathname);
var canPresent = ['code', 'slide'].indexOf(parsed.type) !== -1;
var canBAR = parsed.type !== 'drive';
var burnAfterReading = (hashes.viewHash && canBAR) ?
UI.createRadio('accessRights', 'cp-share-bar', Messages.burnAfterReading_linkBurnAfterReading, false, {
mark: {tabindex:1},
label: {style: "display: none;"}
}) : undefined;
var rights = h('div.msg.cp-inline-radio-group', [
h('label', Messages.share_linkAccess),
h('div.radio-group',[
UI.createRadio('accessRights', 'cp-share-editable-false',
Messages.share_linkView, true, { mark: {tabindex:1} }),
canPresent ? UI.createRadio('accessRights', 'cp-share-present',
Messages.share_linkPresent, false, { mark: {tabindex:1} }) : undefined,
UI.createRadio('accessRights', 'cp-share-editable-true',
Messages.share_linkEdit, false, { mark: {tabindex:1} })]),
burnAfterReading
]);
// Burn after reading
// Check if we are an owner of this pad. If we are, we can show the burn after reading option.
// When BAR is selected, display a red message indicating the consequence and add
// the options to generate the BAR url
opts.barAlert = h('div.alert.alert-danger.cp-alertify-bar-selected', {
style: 'display: none;'
}, Messages.burnAfterReading_warningLink);
var channel = opts.channel = Hash.getSecrets('pad', hash, opts.password).channel;
common.getPadMetadata({
channel: channel
}, function (obj) {
if (!obj || obj.error) { return; }
var priv = common.getMetadataMgr().getPrivateData();
// Not an owner: don't display the burn after reading option
if (!Array.isArray(obj.owners) || obj.owners.indexOf(priv.edPublic) === -1) {
$(burnAfterReading).remove();
return;
}
// When the burn after reading option is selected, transform the modal buttons
$(burnAfterReading).css({
display: 'flex'
});
});
var $rights = $(rights);
opts.saveValue = function () {
var edit = Util.isChecked($rights.find('#cp-share-editable-true'));
var present = Util.isChecked($rights.find('#cp-share-present'));
common.setAttribute(['general', 'share'], {
edit: edit,
present: present
});
};
opts.getLinkValue = function (initValue, cb) {
var val = initValue || {};
var edit = val.edit !== undefined ? val.edit : Util.isChecked($rights.find('#cp-share-editable-true'));
var embed = val.embed;
var present = val.present !== undefined ? val.present : Util.isChecked($rights.find('#cp-share-present'));
var burnAfterReading = Util.isChecked($rights.find('#cp-share-bar'));
if (burnAfterReading && !opts.burnAfterReadingUrl) {
if (cb) { // Called from the contacts tab, "share" button
var barHref = origin + pathname + '#' + (hashes.viewHash || hashes.editHash);
return makeBurnAfterReadingUrl(common, barHref, channel, function (url) {
cb(url);
});
}
return Messages.burnAfterReading_generateLink;
}
var hash = (!hashes.viewHash || (edit && hashes.editHash)) ? hashes.editHash
: hashes.viewHash;
var href = burnAfterReading ? opts.burnAfterReadingUrl
: (origin + pathname + '#' + hash);
var parsed = Hash.parsePadUrl(href);
return origin + parsed.getUrl({embed: embed, present: present});
};
opts.getEmbedValue = function () {
var url = opts.getLinkValue({
embed: true
});
return '<iframe src="' + url + '"></iframe>';
};
// disable edit share options if you don't have edit rights
if (!hashes.editHash) {
$rights.find('#cp-share-editable-false').attr('checked', true);
$rights.find('#cp-share-editable-true').removeAttr('checked').attr('disabled', true);
} else if (!hashes.viewHash) {
$rights.find('#cp-share-editable-false').removeAttr('checked').attr('disabled', true);
$rights.find('#cp-share-present').removeAttr('checked').attr('disabled', true);
$rights.find('#cp-share-editable-true').attr('checked', true);
}
var getLink = function () {
return $rights.parent().find('#cp-share-link-preview');
};
var getEmbed = function () {
return $rights.parent().find('#cp-embed-link-preview');
};
// update values for link and embed preview when radio btns change
$rights.find('input[type="radio"]').on('change', function () {
getLink().val(opts.getLinkValue({
embed: Util.isChecked($('.alertify').find('#cp-share-embed'))
}));
// Hide or show the burn after reading alert
if (Util.isChecked($rights.find('#cp-share-bar')) && !opts.burnAfterReadingUrl) {
$('.cp-alertify-bar-selected').show();
// Show burn after reading button
$('.alertify').find('.cp-bar').show();
$('.alertify').find('.cp-nobar').hide();
return;
}
getEmbed().val(opts.getEmbedValue());
// Hide burn after reading button
$('.alertify').find('.cp-nobar').show();
$('.alertify').find('.cp-bar').hide();
$('.cp-alertify-bar-selected').hide();
});
// Set default values
common.getAttribute(['general', 'share'], function (err, val) {
val = val || {};
if (val.present && canPresent) {
$rights.find('#cp-share-editable-false').prop('checked', false);
$rights.find('#cp-share-editable-true').prop('checked', false);
$rights.find('#cp-share-present').prop('checked', true);
} else if ((val.edit === false && hashes.viewHash) || !hashes.editHash) {
$rights.find('#cp-share-editable-false').prop('checked', true);
$rights.find('#cp-share-editable-true').prop('checked', false);
$rights.find('#cp-share-present').prop('checked', false);
} else {
$rights.find('#cp-share-editable-true').prop('checked', true);
$rights.find('#cp-share-editable-false').prop('checked', false);
$rights.find('#cp-share-present').prop('checked', false);
}
delete val.embed;
if (!canPresent) {
delete val.present;
}
getLink().val(opts.getLinkValue(val));
});
common.getMetadataMgr().onChange(function () {
// "hashes" is only available is the secure "share" app
var _hashes = common.getMetadataMgr().getPrivateData().hashes;
if (!_hashes) { return; }
hashes = _hashes;
getLink().val(opts.getLinkValue());
});
return $rights;
};
// In the share modal, tabs need to share data between themselves.
// To do so we're using "opts" to store data and functions
Share.getShareModal = function (common, opts, cb) {
cb = cb || function () {};
opts = opts || {};
opts.access = true; // Allow the use of the modal even if the pad is not stored
var hashes = opts.hashes;
if (!hashes || (!hashes.editHash && !hashes.viewHash)) { return; }
var teams = getEditableTeams(common, opts);
opts.teams = teams;
var hasFriends = opts.hasFriends = Object.keys(opts.friends || {}).length ||
Object.keys(teams).length;
// check if the pad is password protected
var pathname = opts.pathname;
var hash = hashes.editHash || hashes.viewHash;
var href = pathname + '#' + hash;
var parsedHref = Hash.parsePadUrl(href);
opts.hasPassword = parsedHref.hashData.password;
var $rights = opts.$rights = getRightsHeader(common, opts);
var resetTab = function () {
$rights.show();
$rights.find('label.cp-radio').show();
};
var onShowEmbed = function () {
$rights.find('#cp-share-bar').closest('label').hide();
$rights.find('input[type="radio"]:enabled').first().prop('checked', 'checked');
$rights.find('input[type="radio"]').trigger('change');
};
var onShowContacts = function () {
if (!hasFriends) {
$rights.hide();
}
};
var tabs = [{
getTab: getContactsTab,
title: Messages.share_contactCategory,
icon: "fa fa-address-book",
active: hasFriends,
onShow: onShowContacts,
onHide: resetTab
}, {
getTab: getLinkTab,
title: Messages.share_linkCategory,
icon: "fa fa-link",
active: !hasFriends,
}, {
getTab: getEmbedTab,
title: Messages.share_embedCategory,
icon: "fa fa-code",
onShow: onShowEmbed,
onHide: resetTab
}];
Modal.getModal(common, opts, tabs, function (err, modal) {
$(modal).find('.cp-bar').hide();
// Prepend the "rights" radio selection
$(modal).find('.alertify-tabs-titles').after($rights);
// callback
cb(err, modal);
});
};
var getFileContactsTab = function (Env, data, opts, _cb) {
var cb = Util.once(Util.mkAsync(_cb));
var common = Env.common;
var friendsObject = opts.hasFriends ? createShareWithFriends(opts, null, opts.getLinkValue) : UIElements.noContactsMessage(common);
var friendsList = friendsObject.content;
var contactsContent = h('div.cp-share-modal');
var $contactsContent = $(contactsContent);
$contactsContent.append(friendsList);
// Show alert if the pad is password protected
if (opts.hasPassword) {
$contactsContent.append(h('div.alert.alert-primary', [
h('i.fa.fa-lock'),
Messages.share_linkPasswordAlert, h('br'),
makeFaqLink(opts)
]));
}
var contactButtons = friendsObject.buttons;
contactButtons.unshift(makeCancelButton());
cb(void 0, {
content: contactsContent,
buttons: contactButtons
});
};
var getFileLinkTab = function (Env, data, opts, _cb) {
var cb = Util.once(Util.mkAsync(_cb));
var linkContent = [
UI.dialog.selectableArea(opts.getLinkValue(), {
id: 'cp-share-link-preview', tabindex: 1, rows:2
})
];
// Show alert if the pad is password protected
if (opts.hasPassword) {
linkContent.push(h('div.alert.alert-primary', [
h('i.fa.fa-lock'),
Messages.share_linkPasswordAlert, h('br'),
makeFaqLink(opts)
]));
}
// warning about sharing links
var localStore = window.cryptpadStore;
var dismissButton = h('span.fa.fa-times');
var shareLinkWarning = h('div.alert.alert-warning.dismissable',
{ style: 'display: none;' },
[
h('span.cp-inline-alert-text', Messages.share_linkWarning),
dismissButton
]);
linkContent.push(shareLinkWarning);
localStore.get('hide-alert-shareLinkWarning', function (val) {
if (val === '1') { return; }
$(shareLinkWarning).css('display', 'flex');
$(dismissButton).on('click', function () {
localStore.put('hide-alert-shareLinkWarning', '1');
$(shareLinkWarning).remove();
});
});
var link = h('div.cp-share-modal', linkContent);
var linkButtons = [
makeCancelButton(),
{
className: 'primary',
name: Messages.share_linkCopy,
onClick: function () {
var v = opts.getLinkValue();
var success = Clipboard.copy(v);
if (success) { UI.log(Messages.shareSuccess);
}
},
keys: [13]
}
];
cb(void 0, {
content: link,
buttons: linkButtons
});
};
var getFileEmbedTab = function (Env, data, opts, _cb) {
var cb = Util.once(Util.mkAsync(_cb));
var common = Env.common;
var fileData = opts.fileData;
var embed = h('div.cp-share-modal', [
h('p', Messages.fileEmbedScript),
UI.dialog.selectable(common.getMediatagScript()),
h('p', Messages.fileEmbedTag),
UI.dialog.selectable(common.getMediatagFromHref(fileData)),
]);
// Show alert if the pad is password protected
if (opts.hasPassword) {
$(embed).append(h('div.alert.alert-primary', [
h('i.fa.fa-lock'),
Messages.share_linkPasswordAlert, h('br'),
makeFaqLink(opts)
]));
}
var embedButtons = [{
className: 'cancel',
name: Messages.cancel,
onClick: function () {},
keys: [27]
}, {
className: 'primary',
name: Messages.share_mediatagCopy,
onClick: function () {
var v = common.getMediatagFromHref(opts.fileData);
var success = Clipboard.copy(v);
if (success) { UI.log(Messages.shareSuccess); }
},
keys: [13]
}];
cb(void 0, {
content: embed,
buttons: embedButtons
});
};
Share.getFileShareModal = function (common, opts, cb) {
cb = cb || function () {};
opts = opts || {};
opts.access = true; // Allow the use of the modal even if the pad is not stored
var hashes = opts.hashes;
if (!hashes || !hashes.fileHash) { return; }
var teams = getEditableTeams(common, opts);
opts.teams = teams;
var hasFriends = opts.hasFriends = Object.keys(opts.friends || {}).length ||
Object.keys(teams).length;
// check if the pad is password protected
var origin = opts.origin;
var pathname = opts.pathname;
var url = opts.url = origin + pathname + '#' + hashes.fileHash;
var parsedHref = Hash.parsePadUrl(url);
opts.hasPassword = parsedHref.hashData.password;
opts.getLinkValue = function () { return url; };
var tabs = [{
getTab: getFileContactsTab,
title: Messages.share_contactCategory,
icon: "fa fa-address-book",
active: hasFriends,
}, {
getTab: getFileLinkTab,
title: Messages.share_linkCategory,
icon: "fa fa-link",
active: !hasFriends,
}, {
getTab: getFileEmbedTab,
title: Messages.share_embedCategory,
icon: "fa fa-code",
}];
Modal.getModal(common, opts, tabs, cb);
};
return Share;
});

View File

@ -109,6 +109,13 @@ define([
delete localStorage[k];
delete sessionStorage[k];
});
try {
Object.keys(localStorage || {}).forEach(function (k) {
// Remvoe everything in localStorage except CACHE and FS_hash
if (/^CRYPTPAD_CACHE/.test(k) || /^LESS_CACHE/.test(k) || k === Constants.fileHashKey) { return; }
delete localStorage[k];
});
} catch (e) { console.error(e); }
LocalStore.clearThumbnail();
// Make sure we have an FS_hash in localStorage before reloading all the tabs
// so that we don't end up with tabs using different anon hashes

View File

@ -206,6 +206,10 @@ proxy.mailboxes = {
if (!box) { return void cb(); }
if (!box.cpNf || typeof(box.cpNf.stop) !== "function") { return void cb('EINVAL'); }
box.cpNf.stop();
Object.keys(box.content).forEach(function (h) {
Handlers.remove(ctx, box, box.content[h], h);
hideMessage(ctx, type, h, ctx.clients);
});
delete ctx.boxes[type];
};
var openChannel = function (ctx, type, m, onReady, opts) {

View File

@ -1138,10 +1138,15 @@ define([
teamData.hash = data.hash;
teamData.keys.drive.edPrivate = data.keys.drive.edPrivate;
teamData.keys.chat.edit = data.keys.chat.edit;
initRpc(ctx, team, teamData.keys.drive, function () {});
initRpc(ctx, team, teamData.keys.drive, function () {
team.manager.addPin(team.pin, team.unpin);
});
var secret = Hash.getSecrets('team', data.hash, teamData.password);
team.secondaryKey = secret && secret.keys.secondaryKey;
var crypto = Crypto.createEncryptor(secret.keys);
team.listmap.setReadOnly(false, crypto);
} else {
delete teamData.hash;
delete teamData.keys.drive.edPrivate;
@ -1150,6 +1155,8 @@ define([
if (team.rpc && team.rpc.destroy) {
team.rpc.destroy();
}
team.manager.removePin();
team.listmap.setReadOnly(true);
}
updateMyRights(ctx, teamId, data.hash);

View File

@ -1243,6 +1243,15 @@ define([
};
};
var addPin = function (pin, unpin) {
Env.pinPads = pin;
Env.unpinPads = unpin;
};
var removePin = function () {
delete Env.pinPads;
delete Env.unpinPads;
};
return {
// Manager
addProxy: callWithEnv(addProxy),
@ -1250,6 +1259,8 @@ define([
deprecateProxy: callWithEnv(deprecateProxy),
restrictedProxy: callWithEnv(restrictedProxy),
addSharedFolder: callWithEnv(_addSharedFolder),
addPin: addPin,
removePin: removePin,
// Drive
command: callWithEnv(onCommand),
getPadAttribute: callWithEnv(getPadAttribute),

View File

@ -48,12 +48,19 @@ define([
titleUpdated = cb;
};
var ret = {
updateTitle: exp.updateTitle,
suggestName: suggestTitle,
defaultName: exp.defaultTitle,
getTitle: exp.getTitle
};
metadataMgr.onChange(function () {
var md = metadataMgr.getMetadata();
if ($title) {
$title.find('input').prop('placeholder', md.defaultTitle);
}
exp.defaultTitle = md.defaultTitle;
ret.defaultName = exp.defaultTitle = md.defaultTitle;
});
metadataMgr.onTitleChange(function (title, defaultTitle) {
if ($title) {
@ -79,12 +86,7 @@ define([
});
exp.getTitleConfig = function () {
return {
updateTitle: exp.updateTitle,
suggestName: suggestTitle,
defaultName: exp.defaultTitle,
getTitle: exp.getTitle
};
return ret;
};
exp.onTitleChange = evTitleChange.reg;

View File

@ -0,0 +1 @@
{}

View File

@ -29,7 +29,7 @@
"padNotPinned": "Dieses Pad wird nach 3 Monaten ohne Aktivität auslaufen, {0}logge dich ein{1} oder {2}registriere dich{3}, um das Auslaufen zu verhindern.",
"anonymousStoreDisabled": "Der Webmaster dieses CryptPad-Servers hat die anonyme Verwendung des Speichers deaktiviert. Du musst dich einloggen, um CryptDrive zu verwenden.",
"expiredError": "Dieses Pad ist abgelaufen und ist nicht mehr verfügbar.",
"deletedError": "Dieses Pad wurde von seinem Besitzer gelöscht und ist nicht mehr verfügbar.",
"deletedError": "Dieses Pad wurde von seinem Eigentümer gelöscht und ist nicht mehr verfügbar.",
"inactiveError": "Dieses Pad ist wegen Inaktivität gelöscht worden. Drücke Esc, um ein neues Pad zu erstellen.",
"chainpadError": "Ein kritischer Fehler ist beim Aktualisieren deines Inhalts aufgetreten. Diese Seite ist schreibgeschützt, damit du sicherstellen kannst, dass kein Inhalt verloren geht.<br>Drücke <em>Esc</em>, um das Pad schreibgeschützt zu lesen oder lade es neu, um die Bearbeitung fortzusetzen.",
"errorCopy": " Du kannst noch auf den Inhalt zugreifen, indem du <em>Esc</em> drückst.<br>Wenn du das Fenster schließt, kannst du darauf nicht mehr zugreifen.",
@ -68,8 +68,8 @@
"comingSoon": "Kommt bald...",
"newVersion": "<b>CryptPad wurde aktualisiert!</b><br>Entdecke, was neu in dieser Version ist:<br><a href=\"https://github.com/xwiki-labs/cryptpad/releases/tag/{0}\" target=\"_blank\">Versionshinweise für CryptPad {0}</a>",
"upgrade": "Upgrade",
"upgradeTitle": "Dein Konto upgraden, um mehr Speicherplatz zu haben",
"upgradeAccount": "Konto upgraden",
"upgradeTitle": "Dein Account upgraden, um mehr Speicherplatz zu haben",
"upgradeAccount": "Account upgraden",
"MB": "MB",
"GB": "GB",
"KB": "KB",
@ -105,7 +105,7 @@
"shareSuccess": "Die URL wurde in die Zwischenablage kopiert",
"userListButton": "Benutzerliste",
"chatButton": "Chat",
"userAccountButton": "Dein Konto",
"userAccountButton": "Dein Account",
"newButton": "Neu",
"newButtonTitle": "Neues Pad erstellen",
"uploadButton": "Hochladen",
@ -182,7 +182,7 @@
"hide_help_button": "Hilfe verbergen",
"help_button": "Hilfe",
"historyText": "Verlauf",
"historyButton": "Den Dokumentverlauf anzeigen",
"historyButton": "Dokumentverlauf anzeigen",
"history_next": "Neuere Version",
"history_prev": "Ältere Version",
"history_loadMore": "Weiteren Verlauf laden",
@ -264,7 +264,7 @@
"profile_urlPlaceholder": "URL",
"profile_namePlaceholder": "Angezeigter Name",
"profile_avatar": "Avatar",
"profile_upload": " Einen neuen Avatar hochladen",
"profile_upload": " Neuen Avatar hochladen",
"profile_uploadSizeError": "Fehler: Dein Avatar muss kleiner als {0} sein",
"profile_uploadTypeError": "Fehler: Der Typ dieses Bildes wird nicht unterstützt. Unterstütze Typen sind: {0}",
"profile_error": "Fehler bei der Erstellung deines Profils: {0}",
@ -303,7 +303,7 @@
"fm_filesDataName": "Alle Dateien",
"fm_templateName": "Vorlagen",
"fm_searchName": "Suchen",
"fm_recentPadsName": "Zuletzt geöffnete Pads",
"fm_recentPadsName": "Zuletzt geöffnet",
"fm_ownedPadsName": "Eigene",
"fm_tagsName": "Tags",
"fm_sharedFolderName": "Geteilter Ordner",
@ -345,7 +345,7 @@
"fm_info_recent": "Diese Pads wurden kürzlich von dir oder von Personen, mit denen du zusammenarbeitest, geöffnet oder geändert.",
"fm_info_trash": "Leere den Papierkorb, um mehr freien Platz in deinem CryptDrive zu erhalten.",
"fm_info_allFiles": "Beinhaltet alle Dateien von \"Dokumente\", \"Unsortierte Dateien\" und \"Papierkorb\". Dateien können hier nicht verschoben oder entfernt werden.",
"fm_info_anonymous": "Du bist nicht eingeloggt, daher laufen die Pads nach 3 Monaten aus (<a href=\"https://blog.cryptpad.fr/2017/05/17/You-gotta-log-in/\" target=\"_blank\">mehr dazu lesen</a>). Der Zugang zu den Pads ist in deinem Browser gespeichert, daher wird das Löschen des Browserverlaufs sie möglicherweise verschwinden lassen.<br><a href=\"/register/\">Registriere dich</a> oder <a href=\"/login/\">logge dich ein</a>, um sie dauerhaft zugänglich zu machen.<br>",
"fm_info_anonymous": "Du bist nicht eingeloggt, daher laufen deine Dokumente nach {0} Tagen aus. Sie könnten durch Löschen des Browserverlaufs verloren gehen. <br><a href=\"/register/\">Registriere dich</a> (keine persönlichen Informationen benötigt) oder <a href=\"/login/\">logge dich ein</a>, um sie dauerhaft in deinem Drive zu speichern. <a href=\"https://docs.cryptpad.fr/de/user_guide/user_account.html#account-types\" target=\"_blank\">Mehr zu registrierten Accounts</a>.",
"fm_info_sharedFolder": "Dieser Ordner ist geteilt. Da du aber nicht eingeloggt bist, hast du nur einen schreibgeschützen Zugriff.<br><a href=\"/register/\">Registriere</a> oder <a href=\"/login/\">logge ich ein</a>, damit du diesen Ordner in dein CryptDrive importieren und bearbeiten kannst.",
"fm_info_owned": "Diese Pads sind deine eigenen. Das heißt, dass du sie jederzeit vom Server entfernen kannst. Wenn du das machst, dann sind sie auch für andere Nutzer nicht mehr zugänglich.",
"fm_alert_backupUrl": "Backup-Link für dieses CryptDrive.<br>Es wird <strong>dringend empfohlen</strong>, diesen Link geheim zu halten.<br>Du kannst ihn benutzen, um deine gesamten Dateien abzurufen, wenn dein Browserspeicher gelöscht wurde.<br>Jede Person, die diesen Link hat, kann die Dateien in deinem CryptDrive bearbeiten oder löschen.<br>",
@ -377,7 +377,7 @@
"fc_restore": "Wiederherstellen",
"fc_remove": "Entfernen",
"fc_remove_sharedfolder": "Entfernen",
"fc_empty": "Den Papierkorb leeren",
"fc_empty": "Papierkorb leeren",
"fc_prop": "Eigenschaften",
"fc_hashtag": "Tags",
"fc_sizeInKilobytes": "Größe in Kilobyte",
@ -419,7 +419,7 @@
"register_cancel": "Zurück",
"register_warning": "\"Ohne Preisgabe von Daten\" bedeutet, dass niemand deine Daten wiederherstellen kann, wenn du dein Passwort verlierst.",
"register_alreadyRegistered": "Dieser Benutzer existiert bereits, möchtest du dich einloggen?",
"settings_cat_account": "Konto",
"settings_cat_account": "Account",
"settings_cat_drive": "CryptDrive",
"settings_cat_cursor": "Cursor",
"settings_cat_code": "Code",
@ -467,7 +467,7 @@
"settings_resetThumbnailsDone": "Alle Vorschaubilder wurden entfernt.",
"settings_importTitle": "Importiere die kürzlich besuchten Dokumente in dein CryptDrive",
"settings_import": "Importieren",
"settings_importConfirm": "Bist du sicher, dass du die kürzlich besuchten Pads in das CryptDrive deines Kontos importieren möchtest??",
"settings_importConfirm": "Bist du sicher, dass du die kürzlich besuchten Pads in das CryptDrive deines Accounts importieren möchtest??",
"settings_importDone": "Import abgeschlossen",
"settings_autostoreTitle": "Speichern von Pads im CryptDrive",
"settings_autostoreHint": "<b>Automatisch:</b> Alle Pads werden in deinem CryptDrive gespeichert.<br><b>Manuell (immer nachfragen):</b> Wenn du ein Pad noch nicht gespeichert hast, wirst du gefragt, ob du es im CryptDrive speichern willst.<br><b>Manuell (nie nachfragen):</b> Pads werden nicht automatisch im CryptDrive gespeichert. Die Option zum Speichern wird versteckt.",
@ -478,12 +478,12 @@
"settings_userFeedbackHint1": "CryptPad sendet grundlegende Rückmeldungen zum Server, um die Benutzererfahrung verbessern zu können. ",
"settings_userFeedbackHint2": "Der Inhalt deiner Pads wird nie mit dem Server geteilt.",
"settings_userFeedback": "Rückmeldungen aktivieren",
"settings_deleteTitle": "Löschung des Kontos",
"settings_deleteHint": "Die Löschung eines Kontos ist endgültig. Dein CryptDrive und die Liste deiner Pads werden vom Server gelöscht. Deine restlichen Pads werden nach 90 Tage gelöscht, wenn niemand anderes sie in seinem CryptDrive gespeichert hat.",
"settings_deleteButton": "Dein Konto löschen",
"settings_deleteTitle": "Löschung des Accounts",
"settings_deleteHint": "Die Löschung eines Accounts ist endgültig. Dein CryptDrive und die Liste deiner Pads werden vom Server gelöscht. Deine restlichen Pads werden nach 90 Tage gelöscht, wenn niemand anderes sie in seinem CryptDrive gespeichert hat.",
"settings_deleteButton": "Deinen Account löschen",
"settings_deleteModal": "Gib die folgenden Informationen an deinen CryptPad-Administrator weiter, damit er die Daten vom Server löschen kann.",
"settings_deleteConfirm": "Wenn du auf OK klickst, wird dein Konto dauerhaft gelöscht. Bist du sicher?",
"settings_deleted": "Dein Konto ist jetzt gelöscht. Klicke auf OK, um zur Hauptseite zu gelangen.",
"settings_deleteConfirm": "Wenn du auf OK klickst, wird dein Account dauerhaft gelöscht. Bist du sicher?",
"settings_deleted": "Dein Account ist jetzt gelöscht. Klicke auf OK, um zur Hauptseite zu gelangen.",
"settings_anonymous": "Du bist nicht eingeloggt. Die Einstellungen hier gelten nur für diesen Browser.",
"settings_publicSigningKey": "Öffentlicher Schlüssel zum Unterschreiben",
"settings_usage": "Verbrauch",
@ -515,11 +515,11 @@
"settings_templateSkipHint": "Wenn du ein neues Pad erstellst und passende Vorlagen vorhanden sind, erscheint ein Dialog zur Auswahl einer Vorlage. Hier kannst du diesen Dialog überspringen und somit keine Vorlage verwenden.",
"settings_ownDriveTitle": "Account aktualisieren",
"settings_ownDriveHint": "Aus technischen Gründen sind nicht alle neue Funktionen für ältere Konten verfügbar. Eine kostenlose Aktualisierung wird die neuen Funktionen aktivieren und dein CryptDrive für zukünftige Aktualisierungen vorbereiten.",
"settings_ownDriveButton": "Upgrade deines Kontos",
"settings_ownDriveConfirm": "Das Upgrade deines Kontos kann einige Zeit dauern. Du wirst dich auf allen Geräten neu einloggen müssen. Bist du sicher?",
"settings_ownDrivePending": "Das Upgrade deines Kontos läuft. Bitte schließe die Seite nicht und lade sie nicht neu, bis dieser Vorgang abgeschlossen ist.",
"settings_ownDriveButton": "Upgrade deines Accounts",
"settings_ownDriveConfirm": "Das Upgrade deines Accounts kann einige Zeit dauern. Du wirst dich auf allen Geräten neu einloggen müssen. Bist du sicher?",
"settings_ownDrivePending": "Das Upgrade deines Accounts läuft. Bitte schließe die Seite nicht und lade sie nicht neu, bis dieser Vorgang abgeschlossen ist.",
"settings_changePasswordTitle": "Dein Passwort ändern",
"settings_changePasswordHint": "Ändere das Passwort deines Kontos, ohne deine Daten zu verlieren. Du musst einmal das aktuelle Passwort eingeben und dann das gewünschte neue Passwort zweimal.<br><b>Wir können das Passwort nicht zurücksetzen, wenn du es vergisst. Sei also besonders sorgfältig!</b>",
"settings_changePasswordHint": "Ändere das Passwort deines Accounts, ohne deine Daten zu verlieren. Du musst einmal das aktuelle Passwort eingeben und dann das gewünschte neue Passwort zweimal.<br><b>Wir können das Passwort nicht zurücksetzen, wenn du es vergisst. Sei also besonders sorgfältig!</b>",
"settings_changePasswordButton": "Passwort ändern",
"settings_changePasswordCurrent": "Aktuelles Passwort",
"settings_changePasswordNew": "Neues Passwort",
@ -658,7 +658,7 @@
"features_f_cryptdrive1": "Alle Funktionen des CryptDrives",
"features_f_cryptdrive1_note": "Ordner, geteilte Ordner, Vorlagen, Tags",
"features_f_devices": "Deine Dokumente auf allen deinen Geräten",
"features_f_devices_note": "Überall Zugang zu deinem CryptDrive mit deinem Benutzerkonto",
"features_f_devices_note": "Überall Zugang zu deinem CryptDrive mit deinem Benutzer-Account",
"features_f_social": "Soziale Anwendungen",
"features_f_social_note": "Ein Profil erstellen, ein Profilbild verwenden, mit Kontakten chatten",
"features_f_file1": "Dateien hochladen und teilen",
@ -835,8 +835,8 @@
"save": "Alle Änderungen werden automatisch synchronisiert. Du musst sie also nicht selbst speichern"
},
"text": {
"formatting": "Blende die Werkzeugleiste ein/aus mit der Schaltfläche <i class=\"fa fa-wrench\"></i><b>Werkzeuge</b>.",
"embed": "Füge mit der Schaltfläche <i class=\"fa fa-image\"></i> <b>Insert</b> ein Bild aus deinem CryptDrive oder deinem Computer ein (eingeloggte Benutzer).",
"formatting": "Blende die Werkzeugleiste ein/aus mit der Schaltfläche <i class=\"fa fa-wrench\"></i> <b>Werkzeuge</b>.",
"embed": "Füge mit der Schaltfläche <i class=\"fa fa-image\"></i> <b>Einfügen</b> ein Bild aus deinem CryptDrive oder deinem Computer ein (eingeloggte Benutzer).",
"history": "Du kannst das Menü <em>Verlauf</em> <span class=\"fa fa-history\"></span> benutzen, um frühere Versionen anzusehen oder wiederherzustellen"
},
"pad": {
@ -1294,7 +1294,7 @@
"settings_safeLinksHint": "CryptPad fügt den Pad-Links die Schlüssel zum Entschlüsseln der Inhalte hinzu. Jeder, der Zugriff auf den Browserverlauf hat, kann möglicherweise die Daten lesen. Dazu gehören Browsererweiterungen und Browser, die den Verlauf geräteübergreifend synchronisieren. Die Aktivierung von \"sicheren Links\" verhindert, dass die Schlüssel in den Browserverlauf gelangen oder in der Adressleiste angezeigt werden, wann immer dies möglich ist. Wir empfehlen dringend, diese Funktion zu aktivieren und das Menü {0} Teilen zu verwenden.",
"dontShowAgain": "Nicht mehr anzeigen",
"profile_login": "Du musst dich einloggen, um diesen Benutzer zu deinen Kontakten hinzuzufügen",
"safeLinks_error": "Dieser Link gibt dir keinen Zugriff auf das Dokument",
"safeLinks_error": "Dieser Link wurde aus der Adresszeile des Browsers kopiert und ermöglicht keinen Zugriff auf das Dokument. Bitte verwende das Menü <i class=\"fa fa-shhare-alt\"></i> <b>Teilen</b>, um das Dokument direkt mit Kontakten zu teilen oder den Link zu kopieren. <a href=\"https://docs.cryptpad.fr/de/user_guide/user_account.html#confidentiality\">Mehr zu sicheren Links</a>.\n",
"settings_safeLinksCheckbox": "Sichere Links aktivieren",
"settings_safeLinksTitle": "Sichere Links",
"settings_trimHistoryHint": "Spare Speicherplatz, indem du den Verlauf deines CryptDrives und der Benachrichtigungen löschst. Dies hat keinen Einfluss auf den Verlauf deiner Pads. Du kannst den Verlauf der Pads in deren Eigenschaften-Dialog löschen.",
@ -1384,7 +1384,7 @@
"user_about": "Über CryptPad",
"support_cat_all": "Alle",
"support_cat_other": "Anderes",
"support_cat_account": "Benutzerkonto",
"support_cat_account": "Benutzer-Account",
"support_cat_data": "Datenverlust",
"notification_folderSharedTeam": "{0} hat einen Ordner mit dem Team {2} geteilt: <b>{1}</b>",
"notification_fileSharedTeam": "{0} hat eine Datei mit dem Team {2} geteilt: <b>{1}</b>",

View File

@ -471,7 +471,7 @@
"printBackgroundValue": "<b>Fondo de pantalla actual</b><em>{0</em>}",
"printBackgroundRemove": "Eliminar este fondo de pantalla",
"tags_title": "Etiquetas (sólo para tí)",
"tags_add": "Actualizar las etiquetas de esta página",
"tags_add": "Actualizar las etiquetas para los pads seleccionados",
"tags_notShared": "Tus etiquetas no están compartidas con otros usuarios",
"tags_duplicate": "Duplicar etiquetas:{0}",
"tags_noentry": "No puedes etiquetar una nota eliminada!",

View File

@ -24,7 +24,7 @@
"common_connectionLost": "<b>Yhteys palvelimelle katkennut</b><br>Sovellus on vain luku-tilassa, kunnes yhteys palaa.",
"websocketError": "Yhdistäminen websocket-palvelimelle epäonnistui...",
"typeError": "Tämä padi ei ole yhteensopiva valitun sovelluksen kanssa",
"onLogout": "Olet kirjautunut ulos, {0}klikkaa tästä{1} kirjautuaksesi sisään tai paina <em>Esc-näppäintä</em> käyttääksesi padia vain luku-tilassa.",
"onLogout": "Olet kirjautunut ulos, {0}napsauta tästä{1} kirjautuaksesi sisään tai paina <em>Esc-näppäintä</em> käyttääksesi padia vain luku-tilassa.",
"wrongApp": "Reaaliaikaisen sisällön näyttäminen selaimessa epäonnistui. Ole hyvä ja yritä sivun lataamista uudelleen.",
"padNotPinned": "Tämä padi vanhenee kolmen kuukauden käyttämättömyyden jälkeen, {0}kirjaudu sisään{1} tai [2}rekisteröidy{3} säilyttääksesi sen.",
"padNotPinnedVariable": "Tämä padi vanhenee {4} päivän käyttämättömyyden jälkeen, {0}kirjaudu sisään{1} tai {2}rekisteröidy{3} säilyttääksesi sen.",
@ -33,9 +33,9 @@
"deletedError": "Tämä padi on poistettu omistajansa toimesta, eikä se ole enää saatavilla.",
"inactiveError": "Tämä padi on poistettu käyttämättömyyden vuoksi. Paina Esc-näppäintä luodaksesi uuden padin.",
"chainpadError": "Sisältöä päivitettäessä tapahtui vakava virhe. Tämä sivu on vain luku-tilassa, jotta tekemäsi muutokset eivät katoaisi.<br>Paina <em>Esc-näppäintä</em> jatkaaksesi padin katselua vain luku-tilassa, tai lataa sivu uudelleen yrittääksesi muokkaamista.",
"invalidHashError": "Pyytämäsi dokumentin URL-osoite on virheellinen.",
"invalidHashError": "Pyytämäsi asiakirjan URL-osoite on virheellinen.",
"main_title": "CryptPad: Reaaliaikaista, kollaboratiivista editointia nollatietoperiaatteella",
"errorCopy": " Pääset yhä käyttämään dokumentin sisältöä painamalla <em>Esc</em>-näppäintä.<br>Suljettuasi tämän ikkunan sisältö katoaa, etkä voi enää käyttää sitä.",
"errorCopy": " Pääset yhä käyttämään asiakirjan sisältöä painamalla <em>Esc</em>-näppäintä.<br>Suljettuasi tämän ikkunan sisältö katoaa, etkä voi enää käyttää sitä.",
"errorRedirectToHome": "Paina<em>Esc</em>-näppäintä ohjautuaksesi CryptDriveen.",
"newVersionError": "Uusi versio CryptPadista on saatavilla.<br><a href='#'>Lataa sivu uudelleen</a> siirtyäksesi uuteen versioon, tai paina <em>Esc</em>-näppäintä käyttääksesi sisältöäsi <b>offline-tilassa</b>.",
"loading": "Ladataan...",
@ -48,7 +48,7 @@
"disabledApp": "Tämä sovellus on poistettu käytöstä. Saadaksesi lisätietoja ota yhteyttä tämän CryptPad-instanssin ylläpitäjään.",
"realtime_unrecoverableError": "Tapahtui peruuttamaton virhe. Paina OK ladataksesi uudelleen.",
"disconnected": "Yhteys katkaistu",
"synchronizing": "Synkronisoidaan",
"synchronizing": "Synkronoidaan",
"reconnecting": "Yhdistetään uudelleen",
"typing": "Muokataan",
"initializing": "Valmistellaan...",
@ -99,11 +99,11 @@
"user_rename": "Vaihda näyttönimeä",
"user_displayName": "Näyttönimi",
"user_accountName": "Käyttäjätilin nimi",
"clickToEdit": "Klikkaa muokataksesi",
"clickToEdit": "Napsauta muokataksesi",
"saveTitle": "Tallenna otsikko (Enter)",
"forgetButton": "Poista",
"forgetButtonTitle": "Siirrä padi roskakoriin",
"forgetPrompt": "OK:n klikkaaminen siirtää padin roskakoriin. Oletko varma?",
"forgetPrompt": "OK:n napsauttaminen siirtää padin roskakoriin. Oletko varma?",
"movedToTrash": "Padi on siirretty roskakoriin.<br><a href=\"/drive/\">Siirry Driveen</a>",
"shareButton": "Jaa",
"shareSuccess": "Linkki kopioitu leikepöydälle",
@ -114,7 +114,7 @@
"newButtonTitle": "Luo uusi padi",
"uploadButton": "Lataa tiedostoja palvelimelle",
"uploadFolderButton": "Latauskansio",
"uploadButtonTitle": "Lataa uusi tiedosto nykyiseen kansioon",
"uploadButtonTitle": "Lataa uusi tiedosto CryptDriveesi",
"saveTemplateButton": "Tallenna mallipohjaksi",
"saveTemplatePrompt": "Valitse otsikko mallipohjalle",
"templateSaved": "Mallipohja tallennettu!",
@ -132,7 +132,7 @@
"propertiesButtonTitle": "Hae padin ominaisuudet",
"printText": "Tulosta",
"printButton": "Tulosta (Enter)",
"printButtonTitle2": "Tulosta dokumentti tai vie se PDF-tiedostoon",
"printButtonTitle2": "Tulosta asiakirja tai vie se PDF-tiedostoon",
"printOptions": "Layout-asetukset",
"printSlideNumber": "Näytä dian numero",
"printDate": "Näytä päivämäärä",
@ -150,7 +150,7 @@
"filePicker_filter": "Suodata tiedostot nimen perusteella",
"or": "tai",
"tags_title": "Tunnisteet (vain sinulle)",
"tags_add": "Päivitä sivun tunnisteet",
"tags_add": "Päivitä valittujen padien tunnisteet",
"tags_notShared": "Tunnisteitasi ei jaeta muiden käyttäjien kanssa",
"tags_duplicate": "Kaksinkertainen tunniste: {0}",
"tags_noentry": "Et voi lisätä tunnistetta poistettuun padiin!",
@ -187,14 +187,14 @@
"hide_help_button": "Piilota ohje",
"help_button": "Ohje",
"historyText": "Historia",
"historyButton": "Näytä dokumentin historia",
"historyButton": "Näytä asiakirjan historia",
"history_next": "Uudempi versio",
"history_prev": "Vanhempi versio",
"history_loadMore": "Lataa lisää historiatietoja",
"history_closeTitle": "Sulje historia",
"history_restoreTitle": "Palauta dokumentin valittu versio",
"history_restorePrompt": "Oletko varma, että haluat korvata dokumentin nykyisen version esitetyllä versiolla?",
"history_restoreDone": "Dokumentti palautettu",
"history_restoreTitle": "Palauta asiakirjan valittu versio",
"history_restorePrompt": "Oletko varma, että haluat korvata asiakirjan nykyisen version esitetyllä versiolla?",
"history_restoreDone": "Asiakirja palautettu",
"history_version": "Versio:",
"openLinkInNewTab": "Avaa linkki uuteen välilehteen",
"pad_mediatagTitle": "Media-tunnisteen asetukset",
@ -218,7 +218,7 @@
"poll_subtitle": "Nollatietoperiaatteen mukaista aikataulutusta <em>reaaliajassa</em>",
"poll_p_save": "Asetuksesi otetaan käyttöön välittömästi, joten niitä ei tarvitse tallentaa.",
"poll_p_encryption": "Kaikki tekemäsi syötteet ovat salattuja, joten vain linkin saaneet henkilöt voivat käyttää sitä. Edes itse palvelin ei näe tekemiäsi muutoksia.",
"wizardLog": "Klikkaa vasemmassa yläkulmassa olevaa painiketta palataksesi kyselyyn",
"wizardLog": "Napsauta vasemmassa yläkulmassa olevaa painiketta palataksesi kyselyyn",
"wizardTitle": "Käytä avustajaa kyselyn luomiseen",
"wizardConfirm": "Oletko todella valmis lisäämään nämä vaihtoehdot kyselyysi?",
"poll_publish_button": "Julkaise",
@ -238,7 +238,7 @@
"poll_removeOption": "Oletko varma, että haluat poistaa tämän vaihtoehdon?",
"poll_removeUser": "Oletko varma, että haluat poistaa tämän käyttäjän?",
"poll_titleHint": "Otsikko",
"poll_descriptionHint": "Kuvaile kyselyäsi, ja klikkaa ✓ (Julkaise)-painiketta, kun olet valmis.\nKuvauksen kirjoittamiseen voi käyttää Markdown-syntaksia, ja voit halutessasi upottaa mediaelementtejä CryptDrivestäsi.\nKuka tahansa linkin tietävä voi muuttaa kuvausta, mutta tätä ei suositella.",
"poll_descriptionHint": "Kuvaile kyselyäsi, ja napsauta ✓ (Julkaise)-painiketta, kun olet valmis.\nKuvauksen kirjoittamiseen voi käyttää Markdown-syntaksia, ja voit halutessasi upottaa mediaelementtejä CryptDrivestäsi.\nKuka tahansa linkin tietävä voi muuttaa kuvausta, mutta tätä ei suositella.",
"poll_remove": "Poista",
"poll_edit": "Muokkaa",
"poll_locked": "Lukittu",
@ -251,10 +251,10 @@
"poll_comment_submit": "Lähetä",
"poll_comment_remove": "Poista kommentti",
"poll_comment_placeholder": "Kommenttisi",
"poll_comment_disabled": "Julkaise kysely klikkaamalla ✓ -painiketta ottaaksesi kommentit käyttöön.",
"oo_reconnect": "Yhteys palvelimeen on palannut. Klikkaa OK ladataksesi sivu uudelleen ja jatkaaksesi muokkaamista.",
"poll_comment_disabled": "Julkaise kysely napsauttamalla ✓ -painiketta ottaaksesi kommentit käyttöön.",
"oo_reconnect": "Yhteys palvelimeen on palannut. Napsauta OK ladataksesi sivu uudelleen ja jatkaaksesi muokkaamista.",
"oo_cantUpload": "Tiedostojen lataaminen palvelimelle ei ole sallittua muiden käyttäjien läsnäollessa.",
"oo_uploaded": "Tiedosto on latautunut palvelimelle. Klikkaa OK ladataksesi sivun uudelleen tai Keskeytä jatkaaksesi vain luku-tilassa.",
"oo_uploaded": "Tiedosto on latautunut palvelimelle. Napsauta OK ladataksesi sivun uudelleen tai Keskeytä jatkaaksesi vain luku-tilassa.",
"canvas_clear": "Tyhjennä",
"canvas_delete": "Poista valinta",
"canvas_disable": "Ota piirtäminen pois käytöstä",
@ -280,7 +280,7 @@
"profile_description": "Kuvaus",
"profile_fieldSaved": "Uusi arvo tallennettu: {0}",
"profile_viewMyProfile": "Näytä oma profiili",
"userlist_addAsFriendTitle": "Lähetä kontaktipyyntö käyttäjälle \"{0}\"",
"userlist_addAsFriendTitle": "Lähetä yhteyspyyntö käyttäjälle \"{0}\"",
"contacts_title": "Yhteystiedot",
"contacts_addError": "Virhe lisätessä yhteystietoa listaan",
"contacts_added": "Yhteystietopyyntö hyväksytty.",
@ -293,21 +293,21 @@
"contacts_warning": "Kaikki tähän kirjoittamasi on pysyvää ja saatavilla kaikille tämän padin nykyisille ja tuleville käyttäjille. Olethan varovainen arkaluontoisten tietojen suhteen!",
"contacts_padTitle": "Keskustelu",
"contacts_info1": "Tässä ovat yhteystietosi. Täältä käsin voit:",
"contacts_info2": "Klikkaa yhteystietosi kuvaketta keskustellaksesi hänen kanssaan",
"contacts_info3": "Kaksoisklikkaa yhteystietosi kuvaketta katsellaksesi hänen profiiliaan",
"contacts_info2": "Napsauttaa yhteystietosi kuvaketta keskustellaksesi hänen kanssaan",
"contacts_info3": "Kaksoisnapsauttaa yhteystietosi kuvaketta katsellaksesi hänen profiiliaan",
"contacts_info4": "Kumpi tahansa keskustelun osapuoli voi tyhjentää keskusteluhistorian pysyvästi",
"contacts_removeHistoryTitle": "Tyhjennä keskusteluhistoria",
"contacts_confirmRemoveHistory": "Oletko varma, että haluat tyhjentää keskusteluhistorian pysyvästi? Tietoja ei voida palauttaa",
"contacts_removeHistoryServerError": "Keskusteluhistorian poistamisessa tapahtui virhe. Yritä myöhemmin uudelleen",
"contacts_fetchHistory": "Hae vanhempia viestejä",
"contacts_friends": "Kontaktit",
"contacts_friends": "Yhteystiedot",
"contacts_rooms": "Keskusteluhuoneet",
"contacts_leaveRoom": "Lähde keskusteluhuoneesta",
"contacts_online": "Toinen käyttäjä tästä keskusteluhuoneesta on online-tilassa",
"debug_getGraph": "Hae koodi kaavion luomiseen dokumentin pohjalta",
"debug_getGraph": "Hae koodi kaavion luomiseen asiakirjan pohjalta",
"debug_getGraphWait": "Luodaan kaaviota... Odota hetki.",
"debug_getGraphText": "Tämä on DOT-koodi dokumentin historiakaavion luomiseen:",
"fm_rootName": "Dokumentit",
"debug_getGraphText": "Tämä on DOT-koodi asiakirjan historiakaavion luomiseen:",
"fm_rootName": "Asiakirjat",
"fm_trashName": "Roskakori",
"fm_unsortedName": "Järjestelemättömät tiedostot",
"fm_filesDataName": "Kaikki tiedostot",
@ -336,11 +336,11 @@
"fm_forbidden": "Kielletty toiminto",
"fm_originalPath": "Alkuperäinen polku",
"fm_openParent": "Näytä kansiossa",
"fm_noname": "Nimetön dokumentti",
"fm_noname": "Nimetön asiakirja",
"fm_emptyTrashDialog": "Oletko varma, että haluat tyhjentää roskakorin?",
"fm_removeSeveralPermanentlyDialog": "Oletko varma, että haluat poistaa pysyvästi {0} elementtiä CryptDrivestasi?",
"fm_removeSeveralPermanentlyDialog": "Oletko varma, että haluat poistaa {0} kohdetta CryptDrivestasi? Ne säilyvät edelleen muiden käyttäjien CryptDriveissa.",
"fm_removePermanentlyNote": "Jos jatkat, omistamasi padit poistetaan palvelimelta.",
"fm_removePermanentlyDialog": "Oletko varma, että haluat poistaa tämän elementin CryptDrivestasi?",
"fm_removePermanentlyDialog": "Oletko varma, että haluat poistaa tämän kohteen CryptDrivestasi? Se säilyy edelleen muiden käyttäjien CryptDriveissa.",
"fm_removeSeveralDialog": "Oletko varma, että haluat siirtää {0} elementtiä roskakoriin?",
"fm_removeDialog": "Oletko varma, että haluat siirtää {0} roskakoriin?",
"fm_deleteOwnedPad": "Haluatko varmasti poistaa tämän padin palvelimelta pysyvästi?",
@ -355,8 +355,8 @@
"fm_info_template": "Sisältää kaikki mallipohjiksi tallennetut padit, joita voit käyttää uudelleen luodessasi uuden padin.",
"fm_info_recent": "Tässä näytetään sinun tai yhteistyökumppaniesi äskettäin avaamat tai muokkaamat padit.",
"fm_info_trash": "Tyhjennä roskakorisi vapauttaaksesi CryptDrive-tallennustilaa.",
"fm_info_allFiles": "Sisältää kaikki tiedostot \"Dokumentit\"- \"Lajittelemattomat\"- ja \"Roskakori\"-näkymistä. Et voi siirtää tai poistaa tiedostoja täältä.",
"fm_info_anonymous": "Et ole kirjautunut sisään. Padisi vanhenevat kolmen kuukauden kuluttua (<a href=\"https://blog.cryptpad.fr/2017/05/17/You-gotta-log-in/\" target=\"_blank\">(lue lisää)</a>). Padit säilytetään paikallisesti selaimessasi, joten selaimen historiatietojen tyhjentäminen saattaa hävittää ne.<br><a href=\"/register/\">Rekisteröidy</a> tai <a href=\"/login/\">kirjaudu sisään</a> säilyttääksesi padisi palvelimella.<br>",
"fm_info_allFiles": "Sisältää kaikki tiedostot \"Asiakirjat\"- \"Lajittelemattomat\"- ja \"Roskakori\"-näkymistä. Et voi siirtää tai poistaa tiedostoja täältä.",
"fm_info_anonymous": "Et ole kirjautunut sisään, joten luomasi asiakirjat vanhenevat {0} päivän päästä. Selaushistorian tyhjentäminen saattaa myös hävittää ne.<br><a href=\"/register/\">Rekisteröidy</a> (henkilötietoja ei tarvita) tai <a href=\"/login/\">kirjaudu sisään</a> säilyttääksesi luomasi asiakirjat pysyvästi CryptDrivessa. <a href=\"https://docs.cryptpad.fr/en/user_guide/user_account.html#account-types\" target=\"_blank\">Lue lisää rekisteröitymisestä ja käyttäjätileistä</a>.",
"fm_info_sharedFolder": "Tämä on jaettu kansio. Et ole kirjautunut sisään, joten voit käyttää sitä ainoastaan vain luku-tilassa.<br><a href=\"/register/\">Rekisteröidy</a> tai <a href=\"/login/\">kirjaudu sisään</a> tuodaksesi kansion omaan CryptDriveesi ja muokataksesi sen sisältöä.",
"fm_info_owned": "Omistat tässä näytetyt padit. Se tarkoittaa, että voit halutessasi poistaa ne palvelimelta. Jos teet niin, muut käyttäjät eivät voi enää käyttää niitä.",
"fm_alert_backupUrl": "Driven varmuuskopiointilinkki.<br>On <strong>erittäin suositeltavaa</strong> pitää se salassa.<br>Voit käyttää varmuuskopiointilinkkiä noutaaksesi kaikki Drivellesi tallennetut tiedot, jos selaimesi välimuisti on tyhjentynyt.<br>Kuka tahansa linkin tietävä voi muokata tiedostojasi tai poistaa ne kaikki.<br>",
@ -389,9 +389,9 @@
"fc_expandAll": "Laajenna kaikki",
"fc_collapseAll": "Tiivistä kaikki",
"fc_delete": "Siirrä roskakoriin",
"fc_delete_owned": "Poista palvelimelta",
"fc_delete_owned": "Tuhoa",
"fc_restore": "Palauta",
"fc_remove": "Poista CryptDrivesta",
"fc_remove": "Poista",
"fc_remove_sharedfolder": "Poista",
"fc_empty": "Tyhjennä roskakori",
"fc_prop": "Ominaisuudet",
@ -438,7 +438,7 @@
"register_emailWarning0": "Näyttää siltä, että lähetit sähköpostiosoitteesi käyttäjätunnuksenasi.",
"register_emailWarning1": "Voit halutessasi tehdä niin, mutta sitä ei lähetetä palvelimellemme.",
"register_emailWarning2": "Toisin kuin monissa muissa palveluissa, emme voi palauttaa salasanaasi sähköpostin avulla.",
"register_emailWarning3": "Jos ymmärrät tämän ja haluat silti käyttää sähköpostiosoitettasi käyttäjätunnuksenasi, klikkaa OK.",
"register_emailWarning3": "Jos ymmärrät tämän ja haluat silti käyttää sähköpostiosoitettasi käyttäjätunnuksenasi, napsauta OK.",
"settings_cat_account": "Käyttäjätili",
"settings_cat_drive": "CryptDrive",
"settings_cat_cursor": "Kursori",
@ -456,19 +456,19 @@
"settings_backup2": "Lataa oma CryptDrive tietokoneellesi",
"settings_backup2Confirm": "Tämä lataa kaikki CryptDrivesi padit ja tiedostot tietokoneellesi. Jos haluat jatkaa, valitse nimi ja paina OK",
"settings_exportTitle": "Vie oma CryptDrive",
"settings_exportDescription": "Odota hetki, dokumenttejasi puretaan ja ladataan. Tämä voi viedä muutaman minuutin. Välilehden sulkeminen keskeyttää toimenpiteen.",
"settings_exportDescription": "Odota hetki, asiakirjojasi puretaan ja ladataan. Tämä voi viedä muutaman minuutin. Välilehden sulkeminen keskeyttää toimenpiteen.",
"settings_exportFailed": "Jos padin lataamiseen menee enemmän kuin yksi (1) minuutti, sitä ei oteta mukaan vientiin. Viennistä pois jääneiden padien linkit näytetään lopuksi.",
"settings_exportWarning": "Huomautus: tämä työkalu on beta-versiossa, ja siinä saattaa olla skaalautuvuusongelmia. Suosittelemme välilehden jättämistä aktiiviseksi paremman suorituskyvyn takaamiseksi.",
"settings_exportCancel": "Haluatko varmasti keskeyttää viennin? Seuraavalla kerralla toimenpide täytyy aloittaa alusta.",
"settings_export_reading": "Luetaan CryptDrivea...",
"settings_export_download": "Ladataan ja puretaan dokumentteja...",
"settings_export_download": "Ladataan ja puretaan asiakirjoja...",
"settings_export_compressing": "Pakataan tiedostoja...",
"settings_export_done": "Latauksesi on valmis!",
"settings_exportError": "Tarkastele virheitä",
"settings_exportErrorDescription": "Emme onnistuneet lisäämään seuraavia dokumentteja vientipakettiin:",
"settings_exportErrorEmpty": "Tätä dokumenttia ei voi viedä (tyhjä tai virheellinen sisältö).",
"settings_exportErrorMissing": "Tätä dokumenttia ei löydy palvelimeltamme (vanhentunut tai omistajansa poistama)",
"settings_exportErrorOther": "Dokumenttia viedessä tapahtui virhe: {0}",
"settings_exportErrorDescription": "Emme onnistuneet lisäämään seuraavia asiakirjoja vientipakettiin:",
"settings_exportErrorEmpty": "Tätä asiakirjaa ei voi viedä (tyhjä tai virheellinen sisältö).",
"settings_exportErrorMissing": "Tätä asiakirjaa ei löydy palvelimeltamme (vanhentunut tai omistajansa poistama)",
"settings_exportErrorOther": "Asiakirjaa viedessä tapahtui virhe: {0}",
"settings_resetNewTitle": "Tyhjennä CryptDrive",
"settings_resetButton": "Poista",
"settings_reset": "Poista kaikki tiedostot ja kansiot CryptDrivestasi",
@ -490,7 +490,7 @@
"settings_importConfirm": "Haluatko varmasti tuoda tässä selaimessa viimeksi käytetyt padit käyttäjätilisi CryptDriveen?",
"settings_importDone": "Tuonti valmis",
"settings_autostoreTitle": "Padien tallennus CryptDrivessa",
"settings_autostoreHint": "<b>Automaattinen</b>Kaikki käyttämäsi padit tallennetaan CryptDriveesi.<br><b>Manuaalinen (kysy aina)</b> Jos et ole vielä tallentanut padia, kysytään sinulta, haluatko tallentaa sen CryptDriveesi.<br><b>Manuaalinen (älä kysy)</b>Padeja ei tallenneta automaattisesti CryptDriveesi. Padien tallennusmahdollisuus piilotetaan.",
"settings_autostoreHint": "<b>Automaattinen</b> Kaikki käyttämäsi padit tallennetaan CryptDriveesi.<br><b>Manuaalinen (kysy aina)</b> Jos et ole vielä tallentanut padia, kysytään sinulta, haluatko tallentaa sen CryptDriveesi.<br><b>Manuaalinen (älä kysy)</b> Padeja ei tallenneta automaattisesti CryptDriveesi. Padien tallennusmahdollisuus piilotetaan.",
"settings_autostoreYes": "Automaattinen",
"settings_autostoreNo": "Manuaalinen (älä kysy)",
"settings_autostoreMaybe": "Manuaalinen (kysy aina)",
@ -502,8 +502,8 @@
"settings_deleteHint": "Käyttäjätilin poisto on pysyvä toimenpide. CryptDrivesi ja lista padeistasi poistetaan palvelimelta. Loput padeistasi poistetaan 90 päivän kuluttua, jos kukaan muu ei ole tallentanut niitä omaan CryptDriveensa.",
"settings_deleteButton": "Poista käyttäjätilisi",
"settings_deleteModal": "Jaa seuraavat tiedot CryptPad-instanssisi ylläpitäjän kanssa poistaaksesi tietosi palvelimelta.",
"settings_deleteConfirm": "Klikkaamalla OK käyttäjätilisi poistetaan pysyvästi. Oletko varma?",
"settings_deleted": "Käyttäjätilisi on nyt poistettu. Klikkaa OK siirtyäksesi kotisivulle.",
"settings_deleteConfirm": "Napsauttamalla OK käyttäjätilisi poistetaan pysyvästi. Oletko varma?",
"settings_deleted": "Käyttäjätilisi on nyt poistettu. Napsauta OK siirtyäksesi kotisivulle.",
"settings_anonymous": "Et ole kirjautunut sisään. Nämä asetukset koskevat vain tätä selainta.",
"settings_publicSigningKey": "Julkinen salausavain",
"settings_usage": "Käyttö",
@ -522,10 +522,10 @@
"settings_codeUseTabs": "Sisennä sarkainmerkkejä käyttäen (välilyöntien sijaan)",
"settings_codeFontSize": "Koodieditorin fonttikoko",
"settings_padWidth": "Editorin maksimileveys",
"settings_padWidthHint": "Teksti-tyyppiset padit käyttävät oletusleveytenä näyttölaitteesi maksimileveyttä, mikä voi tehdä lukemisesta vaikeaa. Tästä voit pienentää editorin leveyttä.",
"settings_padWidthHint": "Valitse joko sivutila (oletus), joka rajoittaa tekstieditorin leveyttä tai näyttöruudun täyttä leveyttä käyttävä tila.",
"settings_padWidthLabel": "Pienennä editorin leveyttä",
"settings_padSpellcheckTitle": "Oikeinkirjoituksen tarkistus",
"settings_padSpellcheckHint": "Tämä vaihtoehto ottaa käyttöön oikeinkirjoituksen tarkastuksen Teksti-tyyppisissä padeissa. Oikeinkirjoitusvirheet alleviivataan punaisella. Klikkaa virheellistä sanaa hiiren oikealla painikkeella painaessasi Ctrl- tai Meta-näppäintä pohjaan nähdäksesi korjausehdotukset.",
"settings_padSpellcheckHint": "Tämä vaihtoehto ottaa käyttöön oikeinkirjoituksen tarkastuksen Teksti-tyyppisissä padeissa. Oikeinkirjoitusvirheet alleviivataan punaisella. Napsauta virheellistä sanaa hiiren oikealla painikkeella painaessasi Ctrl- tai Meta-näppäintä pohjaan nähdäksesi korjausehdotukset.",
"settings_padSpellcheckLabel": "Ota oikeinkirjoituksen tarkastus käyttöön Teksti-muotoisissa padeissa",
"settings_creationSkip": "Ohita padin luontiruutu",
"settings_creationSkipHint": "Padien luontisivu esittää vaihtoehtoja padin luomiseen auttaakseen sinua hallitsemaan ja suojaamaan tietojasi. Jos koet sen hidastavan työskentelyäsi, voit tällä asetuksella ohittaa luontisivun ja käyttää sen sijaan yläpuolella määrittelemiäsi oletusasetuksia.",
@ -549,12 +549,12 @@
"settings_changePasswordPending": "Salasanaasi päivitetään. Ole hyvä äläkä sulje tai lataa tätä sivua uudelleen, ennen kuin toimenpide on valmis.",
"settings_changePasswordNewPasswordSameAsOld": "Uuden salasanasi on oltava erilainen kuin nykyinen salasana.",
"settings_cursorColorTitle": "Kursorin väri",
"settings_cursorColorHint": "Vaihda kollaboratiivisissa dokumenteissa käytettävää käyttäjääsi yhdistettyä väriä.",
"settings_cursorColorHint": "Vaihda kollaboratiivisissa asiakirjoissa käytettävää käyttäjääsi yhdistettyä väriä.",
"settings_cursorShareTitle": "Jaa oma kursorisijainti",
"settings_cursorShareHint": "Voit päättää, haluatko kursorisijaintisi näkyvän muille kollaboratiivisissa dokumenteissa.",
"settings_cursorShareHint": "Voit päättää, haluatko kursorisijaintisi näkyvän muille kollaboratiivisissa asiakirjoissa.",
"settings_cursorShareLabel": "Jaa sijainti",
"settings_cursorShowTitle": "Näytä muiden käyttäjien kursorisijainti",
"settings_cursorShowHint": "Voit valita, haluatko nähdä muiden käyttäjien kursorit kollaboratiivisissa dokumenteissa.",
"settings_cursorShowHint": "Voit valita, haluatko nähdä muiden käyttäjien kursorit kollaboratiivisissa asiakirjoissa.",
"settings_cursorShowLabel": "Näytä kursorit",
"upload_title": "Tiedostojen lataus",
"upload_type": "Tyyppi",
@ -570,7 +570,7 @@
"upload_success": "Tiedosto ({0}) on ladattu onnistuneesti palvelimelle ja lisätty CryptDriveesi.",
"upload_notEnoughSpace": "CryptDrivessasi ei ole tarpeeksi vapaata tallennustilaa tälle tiedostolle.",
"upload_notEnoughSpaceBrief": "Tallennustila ei riitä",
"upload_tooLarge": "Tiedoston koko ylittää suurimman sallitun latauskoon.",
"upload_tooLarge": "Tiedoston koko ylittää suurimman käyttäjätilillesi sallitun latauskoon.",
"upload_tooLargeBrief": "Liian suuri tiedosto",
"upload_choose": "Valitse tiedosto",
"upload_pending": "Odottaa",
@ -617,9 +617,9 @@
"about_intro": "CryptPadia kehittää Pariisissa, Ranskassa ja Iasissa, Romaniassa toimiva<a href=\"http://xwiki.com\">XWiki SAS</a>-pienyrityksen tutkimusryhmä. CryptPadin parissa työskentelee kolme ryhmän ydinjäsentä ja lisäksi joitakin avustajia XWiki SAS:n sisältä ja ulkopuolelta.",
"about_core": "Ydinkehittäjät",
"about_contributors": "Tärkeät avustajat",
"main_info": "<h2>Luottamuksellista yhteistyötä</h2> Jaa ideoita yhdessä jaettujen dokumenttien avulla.<strong>Nollatieto</strong>-teknologia turvaa yksityisyytesi - <strong>jopa meiltä</strong>.",
"main_info": "<h2>Luottamuksellista yhteistyötä</h2> Jaa ideoita yhdessä jaettujen asiakirjojen avulla.<strong>Nollatieto</strong>-teknologia turvaa yksityisyytesi - <strong>jopa meiltä</strong>.",
"main_catch_phrase": "Pilvipalvelu nollatietoperiaatteella",
"main_footerText": "CryptPadin avulla voit nopeasti luoda kollaboratiivisia dokumentteja muistiinpanoja ja yhteistä ideointia varten.",
"main_footerText": "CryptPadin avulla voit nopeasti luoda kollaboratiivisia asiakirjoja muistiinpanoja ja yhteistä ideointia varten.",
"footer_applications": "Sovellukset",
"footer_contact": "Ota yhteyttä",
"footer_aboutUs": "Tietoa meistä",
@ -631,14 +631,14 @@
"topbar_whatIsCryptpad": "Mikä on CryptPad",
"whatis_title": "Mikä on CryptPad",
"whatis_collaboration": "Nopeaa ja helppoa yhteistyötä",
"whatis_collaboration_p1": "CryptPadin avulla voit nopeasti luoda kollaboratiivisia dokumentteja muistiinpanoja ja yhteistä ideointia varten. Rekisteröitymällä ja kirjautumalla sisään saat mahdollisuuden ladata tiedostoja palvelimelle ja oman CryptDriven, jossa voit säilyttää kaikki padisi. Rekisteröityneet käyttäjät saavat ilmaiseksi 50 Mt tallennustilaa.",
"whatis_collaboration_p2": "Voit helposti antaa käyttöoikeuden CryptPad-dokumenttiin jakamalla sen linkin. Voit myös jakaa dokumentin linkin <em>vain luku</em>-tilassa, jolloin voit julkistaa yhteistyön tulokset ja muokata niitä edelleen.",
"whatis_collaboration_p1": "CryptPadin avulla voit nopeasti luoda kollaboratiivisia asiakirjoja muistiinpanoja ja yhteistä ideointia varten. Rekisteröitymällä ja kirjautumalla sisään saat mahdollisuuden ladata tiedostoja palvelimelle ja oman CryptDriven, jossa voit säilyttää kaikki padisi. Rekisteröityneet käyttäjät saavat ilmaiseksi 50 Mt tallennustilaa.",
"whatis_collaboration_p2": "Voit helposti antaa käyttöoikeuden CryptPad-dokumenttiin jakamalla sen linkin. Voit myös jakaa asiakirjan linkin <em>vain luku</em>-tilassa, jolloin voit julkistaa yhteistyön tulokset ja muokata niitä edelleen.",
"team_inviteLinkError": "Linkin luomisessa tapahtui virhe.",
"whatis_collaboration_p3": "<a href=\"http://ckeditor.com/\">CKEditor</a>:illa voit luoda yksinkertaisia muotoiltavia tekstitiedostoja sekä Markdown-tiedostoja, jotka muunnetaan tekstiä muokatessasi reaaliaikaisesti esitysmuotoon. Voit myös käyttää Kysely-sovellusta tapahtumien ajoittamiseen useiden osallistujien kanssa.",
"whatis_zeroknowledge": "Nollatietoperiaate",
"whatis_zeroknowledge_p1": "Emme halua tietää, mitä kirjoitat. Modernin kryptografian avulla voit olla varma, ettemme todellakaan tiedä siitä mitään. CryptPad käyttää <strong>100-prosenttisesti asiakasohjelmassa tapahtuvaa salausta</strong> suojatakseen tuottamaasi sisältöä meiltä palvelimen ylläpitäjiltä.",
"whatis_zeroknowledge_p2": "Rekisteröityessäsi ja kirjautuessasi sisään käyttäjätunnuksesi ja salasanasi lasketaan salaiseksi avaimeksi <a href=\"https://en.wikipedia.org/wiki/Scrypt\">scrypt-avaintenmuodostusfunktiolla</a>. Tätä avainta, käyttäjätunnustasi ja salasanaasi ei koskaan lähetetä palvelimelle. Sen sijaan niitä käytetään asiakasohjelmassa CryptDrivesi sisällön purkamiseen. CryptDrivesi puolestaan sisältää avaimet kaikkiin padeihin, joihin sinulla on käyttöoikeus.",
"whatis_zeroknowledge_p3": "Kun jaat linkin dokumenttiin, jaat itse asiassa dokumentin käyttöön tarvittavan salausavaimen, mutta koska salausavain sisällytetään <a href=\"https://en.wikipedia.org/wiki/Fragment_identifier\">katkelmatunnisteeseen (fragment identifier)</a>, sitä ei koskaan lähetetä palvelimelle suoraan. Tutustu <a href=\"https://blog.cryptpad.fr/2017/07/07/cryptpad-analytics-what-we-cant-know-what-we-must-know-what-we-want-to-know/\">yksityisyydestä kertovaan blogikirjoitukseemme</a> saadaksesi selville, mihin metadataan meillä on pääsy ja mihin taas ei.",
"whatis_zeroknowledge_p3": "Kun jaat linkin asiakirjaan, jaat itse asiassa asiakirjan käyttöön tarvittavan salausavaimen, mutta koska salausavain sisällytetään <a href=\"https://en.wikipedia.org/wiki/Fragment_identifier\">katkelmatunnisteeseen (fragment identifier)</a>, sitä ei koskaan lähetetä palvelimelle suoraan. Tutustu <a href=\"https://blog.cryptpad.fr/2017/07/07/cryptpad-analytics-what-we-cant-know-what-we-must-know-what-we-want-to-know/\">yksityisyydestä kertovaan blogikirjoitukseemme</a> saadaksesi selville, mihin metadataan meillä on pääsy ja mihin taas ei.",
"whatis_drive": "CryptDriven järjestely",
"whatis_drive_p1": "Kun käytät padia CryptPadissa, lisätään se automaattisesti CryptDrivesi pääkansioon. Voit halutessasi myöhemmin järjestellä padit kansioihin tai viedä ne roskakoriin. CryptDrive antaa sinun hakea padejasi ja järjestellä niitä milloin ja miten haluat.",
"whatis_drive_p2": "Intuitiivinen raahaa ja pudota-käyttöliittymä mahdollistaa padien siirtelemisen CryptDrivessa niin, etteivät niiden linkit muutu, eivätkä padien osallistujat siten koskaan menetä käyttöoikeuttaan niihin.",
@ -647,7 +647,7 @@
"admin_activeSessionsTitle": "Aktiiviset yhteydet",
"admin_activeSessionsHint": "Aktiivisten WebSocket-yhteyksien määrä (ja yhdistetyt uniikit IP-osoitteet)",
"admin_activePadsTitle": "Aktiiviset padit",
"admin_activePadsHint": "Tällä hetkellä katseltavien tai muokattavien uniikkien dokumenttien määrä",
"admin_activePadsHint": "Tällä hetkellä katseltavien tai muokattavien uniikkien asiakirjojen määrä",
"admin_registeredTitle": "Rekisteröityneet käyttäjät",
"admin_registeredHint": "CryptPad-instanssiisi rekisteröityneiden käyttäjien määrä",
"admin_updateLimitTitle": "Päivitä käyttäjien tallennuskiintiöt",
@ -655,7 +655,7 @@
"admin_updateLimitButton": "Päivitä tallennuskiintiöt",
"admin_updateLimitDone": "Päivitys onnistui",
"admin_flushCacheTitle": "Tyhjennä HTTP-välimuisti",
"notifications_cat_friends": "Kaveripyynnöt",
"notifications_cat_friends": "Yhteyspyynnöt",
"notifications_cat_pads": "Kanssani jaetut",
"notifications_cat_archived": "Historia",
"notifications_dismissAll": "Hylkää kaikki",
@ -674,10 +674,10 @@
"features_noData": "Henkilötietoja ei tarvita",
"features_pricing": "{0}-{2}€/kk",
"features_emailRequired": "Sähköpostiosoite vaaditaan",
"owner_removeText": "Poista olemassaoleva omistaja",
"owner_removePendingText": "Peru odottava tarjous",
"owner_addText": "Tarjoa yhteisomistajuutta kaverille",
"owner_unknownUser": "Tuntematon käyttäjä",
"owner_removeText": "Omistajat",
"owner_removePendingText": "Odottavat",
"owner_addText": "Tarjoa yhteisomistajuutta yhteystiedolle",
"owner_unknownUser": "tuntematon",
"owner_removeButton": "Poista valitut omistajat",
"owner_removePendingButton": "Peru valitut tarjoukset",
"owner_addButton": "Tarjoa omistajuutta",
@ -689,7 +689,7 @@
"owner_request": "{0} haluaa sinut <b>{1}</b> omistajaksi",
"owner_request_accepted": "{0} on hyväksynyt tarjouksesi <b>{1}</b> omistajuudesta",
"share_linkTeam": "Lisää tiimin CryptDriveen",
"team_pickFriends": "Valitse tiimiin kutsuttavat kaverit",
"team_pickFriends": "Valitse tiimiin kutsuttavat yhteystiedot",
"team_inviteModalButton": "Kutsu",
"drive_sfPassword": "Jaettu kansiosi {0} ei ole enää saatavilla. Se on joko poistettu omistajansa toimesta tai sille on asetettu uusi salasana. Voit poistaa tämän kansion CryptDrivestasi tai palauttaa käyttöoikeuden käyttämällä uutta salasanaa.",
"drive_sfPasswordError": "Väärä salasana",
@ -711,7 +711,7 @@
"teams_table_owners": "Hallitse tiimiä",
"teams_table_role": "Rooli",
"pad_wordCount": "Sanamäärä: {0}",
"share_linkWarning": "Tämä linkki sisältää dokumenttisi avaimet. Linkin vastaanottajat saavat dokumenttiisi käyttöoikeudet, joita ei voi poistaa jälkikäteen.",
"share_linkWarning": "Tämä linkki sisältää asiakirjasi avaimet. Linkin vastaanottajat saavat asiakirjaasi käyttöoikeudet, joita ei voi poistaa jälkikäteen.",
"share_linkPasswordAlert": "Tämä elementti on salasanasuojattu. Kun lähetät linkin, täytyy vastaanottajan syöttää salasana.",
"share_contactPasswordAlert": "Tämä elementti on salasanasuojattu. Koska jaat sen CryptPad-yhteyshenkilön kanssa, ei vastaanottajan tarvitse syöttää salasanaa.",
"share_embedPasswordAlert": "Tämä elementti on salasanasuojattu. Kun upotat tämän padin, katselijoita pyydetään syöttämään salasana.",
@ -745,67 +745,67 @@
"team_cat_link": "Kutsulinkki",
"team_links": "Kutsulinkit",
"team_inviteInvalidLinkError": "Tämä kutsulinkki ei ole kelvollinen.",
"notificationsPage": "",
"openNotificationsApp": "",
"notifications_cat_all": "",
"owner_request_declined": "",
"owner_removed": "",
"owner_removedPending": "",
"team_pcsSelectLabel": "",
"team_pcsSelectHelp": "",
"team_invitedToTeam": "",
"team_kickedFromTeam": "",
"team_acceptInvitation": "",
"team_declineInvitation": "",
"team_cat_general": "",
"team_cat_list": "",
"team_cat_create": "",
"team_cat_back": "",
"team_cat_members": "",
"team_cat_chat": "",
"team_cat_drive": "",
"team_cat_admin": "",
"team_infoLabel": "",
"team_listLoad": "",
"team_createLabel": "",
"team_createName": "",
"team_rosterPromote": "",
"team_rosterDemote": "",
"team_rosterKick": "",
"team_inviteButton": "",
"team_leaveButton": "",
"team_leaveConfirm": "",
"team_owner": "",
"team_admins": "",
"team_members": "",
"team_nameTitle": "",
"team_nameHint": "",
"team_avatarTitle": "",
"team_avatarHint": "",
"team_infoContent": "",
"team_maxOwner": "",
"team_maxTeams": "",
"team_listTitle": "",
"team_listSlot": "",
"owner_addTeamText": "",
"owner_team_add": "",
"team_rosterPromoteOwner": "",
"team_ownerConfirm": "",
"team_kickConfirm": "",
"sent": "",
"team_pending": "",
"team_deleteTitle": "",
"team_deleteHint": "",
"team_deleteButton": "",
"team_deleteConfirm": "",
"team_pendingOwner": "",
"team_pendingOwnerTitle": "",
"team_demoteMeConfirm": "",
"team_title": "",
"team_quota": "",
"drive_quota": "",
"settings_codeBrackets": "",
"team_viewers": "",
"notificationsPage": "Ilmoitukset",
"openNotificationsApp": "Avaa ilmoituspaneeli",
"notifications_cat_all": "Kaikki",
"owner_request_declined": "{0} on kieltäytynyt tarjoamastasi <b>{1}</b> omistajuudesta",
"owner_removed": "{0} on poistanut omistajuutesi <b>{1}</b>",
"owner_removedPending": "{0} on perunut omistajuustarjouksesi <b>{1}</b>",
"team_pcsSelectLabel": "Tallenna sijaintiin",
"team_pcsSelectHelp": "Omistetun padin luominen tiimin CryptDriveen antaa padin omistajuuden tiimille.",
"team_invitedToTeam": "{0} on kutsunut sinut tiimiin: <b>{1}</b>",
"team_kickedFromTeam": "{0} on potkinut sinut tiimistä: <b>{1}</b>",
"team_acceptInvitation": "{0} on hyväksynyt tarjouksesi liittyä tiimiin: <b>{1}</b>",
"team_declineInvitation": "{0} on kieltäytynyt tarjouksesta liittyä tiimiin: <b>{1}</b>",
"team_cat_general": "Tietoja",
"team_cat_list": "Tiimit",
"team_cat_create": "Uusi",
"team_cat_back": "Takaisin tiimeihin",
"team_cat_members": "Jäsenet",
"team_cat_chat": "Keskustelu",
"team_cat_drive": "CryptDrive",
"team_cat_admin": "Ylläpito",
"team_infoLabel": "Tietoa tiimeistä",
"team_listLoad": "Avaa",
"team_createLabel": "Luo uusi tiimi",
"team_createName": "Tiimin nimi",
"team_rosterPromote": "Ylennä",
"team_rosterDemote": "Alenna",
"team_rosterKick": "Potki tiimistä",
"team_inviteButton": "Kutsu jäseniä",
"team_leaveButton": "Lähde tiimistä",
"team_leaveConfirm": "Jos poistut tiimistä, menetät käyttöoikeutesi sen CryptDriveen, keskusteluhistoriaan ja muuhun sisältöön. Oletko varma?",
"team_owner": "Omistajat",
"team_admins": "Ylläpitäjät",
"team_members": "Jäsenet",
"team_nameTitle": "Tiimin nimi",
"team_nameHint": "Määritä tiimin nimi",
"team_avatarTitle": "Tiimin avatar-kuva",
"team_avatarHint": "Kuvan maksimikoko 500Kt (png, jpg, jpeg, gif)",
"team_infoContent": "Jokaisella tiimillä on oma CryptDrive, tallennustilakiintiö, keskustelualue ja jäsenlista. Tiimien omistajat voivat poistaa tiimin. Ylläpitäjät voivat kutsua tai poistaa jäseniä. Jäsenet voivat lähteä tiimistä.",
"team_maxOwner": "Jokainen käyttäjätili voi omistaa ainoastaan yhden tiimin.",
"team_maxTeams": "Käyttäjätili voi olla jäsenenä vain {0} tiimissä.",
"team_listTitle": "Omat tiimit",
"team_listSlot": "Avoin tiimipaikka",
"owner_addTeamText": "...tai tiimi",
"owner_team_add": "{0} haluaa sinut omistajaksi tiimiin <b>{1}</b>. Hyväksytkö tarjouksen?",
"team_rosterPromoteOwner": "Tarjoa omistajuutta",
"team_ownerConfirm": "Yhteisomistajat voivat muokata tiimiä, poistaa sen kokonaan tai poistaa omistajuutesi. Oletko varma?",
"team_kickConfirm": "{0} saa tietää, että olet poistanut tämän tiimistä. Oletko varma?",
"sent": "Viesti lähetetty",
"team_pending": "Kutsuttu",
"team_deleteTitle": "Tiimin poisto",
"team_deleteHint": "Poista tiimi ja kaikki yksinomaan tiimin omistamat asiakirjat.",
"team_deleteButton": "Poista",
"team_deleteConfirm": "Olet poistamassa kaikki tiimin tiedot. Tämä voi vaikuttaa muiden tiimin jäsenien omien tietojen käyttöön. Toimintoa ei voi perua. Oletko varma, että haluat jatkaa?",
"team_pendingOwner": "(odottaa)",
"team_pendingOwnerTitle": "Tämä ylläpitäjä ei ole vielä hyväksynyt omistajuustarjousta.",
"team_demoteMeConfirm": "Olet luopumassa oikeuksistasi. Tätä toimintoa ei voi perua. Oletko varma?",
"team_title": "Tiimi: {0}",
"team_quota": "Tiimisi tallennustilakiintiö",
"drive_quota": "Tallennustilakiintiösi",
"settings_codeBrackets": "Sulje sulkeet automaattisesti",
"team_viewers": "Katselijat",
"whatis_business_p1": "CryptPadin nollatietoperiaate-salaus moninkertaistaa olemassaolevien tietoturvaprotokollien tehokkuuden peilaamalla organisaation pääsynvalvontaa kryptografiassa. Arkaluonteisten tietojen purkamiseen tarvitaan aina käyttäjän kirjautumistiedot, joten CryptPad on potentiaaliselle hyökkääjälle perinteisiä pilvipalveluita vähempiarvoisempi kohde. Lue lisää hyödyistä yrityksille <a href='https://blog.cryptpad.fr/images/CryptPad-Whitepaper-v1.0.pdf'>CryptPad Whitepaper-julkaisusta</a>.",
"whatis_business_p2": "Cryptpad on saatavilla on-premises-ratkaisuna, ja XWiki SAS:n<a href=\"https://cryptpad.fr/about.html\">CryptPad-kehittäjät</a> tarjoavat kaupallista tukea sekä räätälöinti- ja kehityspalveluita. Ota yhteyttä osoitteeseen <a href=\"mailto:sales@cryptpad.fr\">sales@cryptpad.fr</a> saadaksesi lisätietoja.",
"policy_title": "CryptPad-tietosuojakäytäntö",
@ -823,7 +823,7 @@
"policy_choices": "Vaihtoehtosi",
"policy_choices_open": "Lähdekoodimme on avointa, joten voit halutessasi perustaa oman CryptPad-instanssisi.",
"policy_choices_vpn": "Jos haluat käyttää ylläpitämäämme CryptPad-instanssia, mutta et paljastaa IP-osoitettasi, voit suojata sen käyttämällä <a href=\"https://www.torproject.org/projects/torbrowser.html.en\" title=\"downloads from the Tor project\" target=\"_blank\" rel=\"noopener noreferrer\">Tor-selainpakettia</a> tai <a href=\"https://riseup.net/en/vpn\" title=\"VPNs provided by Riseup\" target=\"_blank\" rel=\"noopener noreferrer\">VPN-palvelua</a>.",
"policy_choices_ads": "Jos haluat ainoastaan estää analytiikkapalvelumme, voit käyttää mainosten estämiseen tarkoitettuja työkaluja, kuten <a hre=\"https://www.eff.org/privacybadger\" title=\"download privacy badger\" target=\"_blank\" rel=\"noopener noreferrer\">Privacy Badgeria</a>.",
"policy_choices_ads": "Jos haluat ainoastaan estää analytiikkapalvelumme, voit käyttää mainosten estämiseen tarkoitettuja työkaluja, kuten <a href=\"https://www.eff.org/privacybadger\" title=\"download privacy badger\" target=\"_blank\" rel=\"noopener noreferrer\">Privacy Badgeria</a>.",
"features": "Ominaisuudet",
"features_title": "Ominaisuuksien vertailu",
"features_feature": "Ominaisuus",
@ -849,7 +849,7 @@
"features_f_social": "Sosiaaliset sovellukset",
"features_f_social_note": "Luo käyttäjäprofiili, käytä avatar-kuvaa, keskustele yhteystietojen kanssa",
"features_f_file1": "Lataa ja jaa tiedostoja",
"features_f_file1_note": "Jaa tiedostoja kontaktiesi kanssa tai upota ne padeihisi",
"features_f_file1_note": "Jaa tiedostoja yhteystietojesi kanssa tai upota ne padeihisi",
"features_f_storage1": "Pysyvä tallennustila (50Mt)",
"features_f_storage1_note": "CryptDriveen tallennettuja padeja ei koskaan poisteta käyttämättömyyden takia",
"features_f_register": "Rekisteröidy ilmaiseksi",
@ -872,7 +872,7 @@
"title": "Avainsanat",
"pad": {
"q": "Mikä on padi?",
"a": "<em>Padi</em> on <a href='http://etherpad.org/' target='_blank'>Etherpad-projektin</a> popularisoima termi reaaliaikaiselle kollaboratiiviselle editorille.\nSe tarkoittaa selaimessa muokattavaa dokumenttia, jossa muiden käyttäjien tekemät muutokset näkyvät lähes välittömästi."
"a": "<em>Padi</em> on <a href='http://etherpad.org/' target='_blank'>Etherpad-projektin</a> popularisoima termi reaaliaikaiselle kollaboratiiviselle editorille.\nSe tarkoittaa selaimessa muokattavaa asiakirjaa, jossa muiden käyttäjien tekemät muutokset näkyvät lähes välittömästi."
},
"owned": {
"q": "Mikä on omistettu padi?",
@ -884,15 +884,15 @@
},
"tag": {
"q": "Miten voin käyttää tunnisteita?",
"a": "Voit lisätä padeihin ja ladattuihin tiedostoihin tunnisteita CryptDrivessa tai käyttää <em>Tunniste</em>-painiketta (<span class='fa fa-hashtag'></span>) minkä tahansa editorin työkalupalkista. Hae padeja ja tiedostoja CryptDriven hakupalkista käyttämällä ristikkomerkillä alkavaa hakusanaa (esimerkiksi <em>#crypto</em>)."
"a": "Voit lisätä padeihin ja ladattuihin tiedostoihin tunnisteita CryptDrivessa tai käyttää <em>Tunniste</em>-painiketta (<span class='fa fa-hashtag'></span>) minkä tahansa editorin työkalupalkista. Hae padeja ja tiedostoja CryptDriven hakupalkista käyttämällä ristikkomerkillä alkavaa hakusanaa (esimerkiksi <em>#crypto</em>)."
},
"template": {
"q": "Mikä on mallipohja?",
"a": "Mallipohja on padi, jolla voit määritellä luotavan padin oletussisällön luodessasi toista samantyyppistä padia. Voit muuttaa minkä tahansa olemassaolevan padin mallipohjaksi siirtämällä sen <em>Mallipohjat</em>-osastoon CryptDrivessasi. Voit myös tehdä padista mallipohjana käytettävän kopion klikkaamalla Mallipohja-painiketta (<span class='fa fa-bookmark'></span>) editorin työkalupalkista."
"a": "Mallipohja on padi, jolla voit määritellä luotavan padin oletussisällön luodessasi toista samantyyppistä padia. Voit muuttaa minkä tahansa olemassaolevan padin mallipohjaksi siirtämällä sen <em>Mallipohjat</em>-osastoon CryptDrivessasi. Voit myös tehdä padista mallipohjana käytettävän kopion napsauttamalla Mallipohja-painiketta (<span class='fa fa-bookmark'></span>) editorin työkalupalkista."
},
"abandoned": {
"q": "Mikä on hylätty padi?",
"a": "<em>Hylätty padi</em> on padi, jota ei ole kiinnitetty yhdenkään rekisteröityneen käyttäjän CryptDriveen ja jota ei ole muokattu kuuteen kuukauteen. Hylätyt dokumentit poistetaan palvelimelta automaattisesti."
"a": "<em>Hylätty padi</em> on padi, jota ei ole kiinnitetty yhdenkään rekisteröityneen käyttäjän CryptDriveen ja jota ei ole muokattu kuuteen kuukauteen. Hylätyt asiakirjat poistetaan palvelimelta automaattisesti."
}
},
"privacy": {
@ -925,7 +925,7 @@
"security": {
"pad_password": {
"q": "Mitä tapahtuu, kun suojaan padin tai kansion salasanalla?",
"a": "Voit suojata minkä tahansa padin tai jaetun kansion salasanalla luodessasi sen. Voit myös käyttää Ominaisuudet-valikkoa asettaaksesi, vaihtaaksesi tai poistaaksesi salasanan milloin tahansa.<br><br>Padien ja jaettujen kansioiden salasanat on tarkoitettu suojaamaan linkkiä jakaessasi sitä mahdollisesti turvattomien kanavien, kuten sähköpostin tai tekstiviestin kautta. Jos joku onnistuu kaappaamaan linkkisi, mutta ei tiedä sen salasanaa, ei hän pääse lukemaan dokumenttiasi.<br><br>Kun jaat sisältöä CryptPadin sisällä yhteystietojesi tai tiimiesi kanssa, tiedonsiirto on salattua ja oletamme, että haluat heidän pääsevän käyttämään dokumenttiasi. Siksi salasana tallennetaan ja lähetetään padin mukana jakaessasi sitä CryptPadin sisällä. Vastaanottajalta tai sinulta itseltäsi <b>ei</b> pyydetä salasanaa dokumenttia avatessa."
"a": "Voit suojata minkä tahansa padin tai jaetun kansion salasanalla luodessasi sen. Voit myös käyttää Ominaisuudet-valikkoa asettaaksesi, vaihtaaksesi tai poistaaksesi salasanan milloin tahansa.<br><br>Padien ja jaettujen kansioiden salasanat on tarkoitettu suojaamaan linkkiä jakaessasi sitä mahdollisesti turvattomien kanavien, kuten sähköpostin tai tekstiviestin kautta. Jos joku onnistuu kaappaamaan linkkisi, mutta ei tiedä sen salasanaa, ei hän pääse lukemaan asiakirjaasi.<br><br>Kun jaat sisältöä CryptPadin sisällä yhteystietojesi tai tiimiesi kanssa, tiedonsiirto on salattua ja oletamme, että haluat heidän pääsevän käyttämään asiakirjaasi. Siksi salasana tallennetaan ja lähetetään padin mukana jakaessasi sitä CryptPadin sisällä. Vastaanottajalta tai sinulta itseltäsi <b>ei</b> pyydetä salasanaa asiakirjaa avatessa."
},
"title": "Turvallisuus",
"proof": {
@ -952,12 +952,12 @@
"a": "Rekisteröityneille käyttäjille on tarjolla joitakin toimintoja, jotka eivät ole saatavilla rekisteröitymättömille käyttäjille. Löydät nämä toiminnot <a href='/features.html' target='_blank'>luomastamme kaaviosta</a>."
},
"share": {
"q": "Miten jaan salattuja padeja kontaktieni kanssa?",
"q": "Miten jaan salattuja padeja yhteystietojeni kanssa?",
"a": "CryptPad laittaa URL-osoitteessa padisi salaisen salausavaimen <em>#</em>-merkin jälkeen. Tämän merkin jälkeen laitettuja tietoja ei lähetetä palvelimelle, joten emme pääse koskaan käyttämään salausavaimiasi. Jakaessasi linkin padiin jaat oikeuden lukea ja käyttää sitä."
},
"remove": {
"q": "Poistin padin tai tiedoston CryptDrivestani, mutta sen sisältö on yhä käytettävissä. Miten voin poistaa sen?",
"a": "Ainoastaan <em>omistettuja padeja</em> (otettu käyttöön helmikuussa 2018) voi poistaa. Lisäksi nämä padit voi poistaa ainoastaan niiden <em>omistaja</em> eli henkilö, joka alun perin loi kyseisen padin. Jos et ole luonut kyseistä padia, joudut pyytämään sen omistajaa poistamaan sen puolestasi. Omistamiesi padien poistaminen onnistuu CryptDrivessa <strong>klikkaamalla padia hiiren oikealla painikkeella</strong> ja valitsemalla <strong>Poista palvelimelta</strong>."
"a": "Ainoastaan <em>omistettuja padeja</em> (otettu käyttöön helmikuussa 2018) voi poistaa. Lisäksi nämä padit voi poistaa ainoastaan niiden <em>omistaja</em> eli henkilö, joka alun perin loi kyseisen padin. Jos et ole luonut kyseistä padia, joudut pyytämään sen omistajaa poistamaan sen puolestasi. Omistamiesi padien poistaminen onnistuu CryptDrivessa <strong>napsauttamalla padia hiiren oikealla painikkeella</strong> ja valitsemalla <strong>Poista palvelimelta</strong>."
},
"forget": {
"q": "Mitä tapahtuu, jos unohdan salasanani?",
@ -977,14 +977,14 @@
},
"feature": {
"q": "Voitteko lisätä CryptPadiin tarvitsemani ominaisuuden?",
"a": "Monet CryptPadin ominaisuuksista ovat olemassa, koska käyttäjämme ovat toivoneet niitä. <a href='https://cryptpad.fr/contact.html' target='_blank'>Yhteystiedot-sivumme</a> kertoo, millä tavoin meihin saa yhteyden.<br><br>Valitettavasti emme voi taata, että pystymme toteuttamaan kaikki käyttäjiemme ehdotukset. Jos jokin tietty ominaisuus on kriittinen organisaatiosi kannalta, voit sponsoroida kehitystä varmistaaksesi sen toteutumisen. Ota yhteyttä osoitteeseen <a href='mailto:sales@cryptpad.fr' target='_blank'>sales@cryptpad.fr</a> saadaksesi lisätietoja.<br><br>Vaikka kehitystyön sponsorointi ei olisikaan mahdollista, olemme silti kiinnostuneita palautteesta, joka auttaa meitä parantamaan CryptPadia. Ota meihin milloin tahansa yhteyttä yllä luetelluilla tavoilla."
"a": "Monet CryptPadin ominaisuuksista ovat olemassa, koska käyttäjämme ovat toivoneet niitä. <a href='https://cryptpad.fr/contact.html' target='_blank'>Yhteystiedot-sivumme</a> kertoo, millä tavoin meihin saa yhteyden.<br><br>Valitettavasti emme voi taata, että pystymme toteuttamaan kaikki käyttäjiemme ehdotukset. Jos jokin tietty ominaisuus on kriittinen organisaatiosi kannalta, voit sponsoroida kehitystä varmistaaksesi sen toteutumisen. Ota yhteyttä osoitteeseen <a href='mailto:sales@cryptpad.fr' target='_blank'>sales@cryptpad.fr</a> saadaksesi lisätietoja.<br><br>Vaikka kehitystyön sponsorointi ei olisikaan mahdollista, olemme silti kiinnostuneita palautteesta, joka auttaa meitä parantamaan CryptPadia. Ota meihin milloin tahansa yhteyttä yllä luetelluilla tavoilla."
}
},
"other": {
"title": "Muita kysymyksiä",
"pay": {
"q": "Miksi minun täytyisi maksaa, kun niin monet toiminnot ovat ilmaisia?",
"a": "Annamme tukijoillemme lisätallennustilaa ja mahdollisuuden kasvattaa kontaktien tallennustilakiintiöitä (<a href='https://accounts.cryptpad.fr/#/faq' target='_blank'>lue lisää</a>).<br><br>Näiden lyhytaikaisten etujen lisäksi premium-tilaus auttaa rahoittamaan CryptPadin jatkuvaa, aktiivista kehitystyötä. Tähän kuuluu bugien korjaamista, uusien ominaisuuksien lisäämistä ja CryptPad-instanssien pystyttämisen ja ylläpidon helpottamista. Lisäksi autat näyttämään muille palveluntarjoajille, että ihmiset ovat valmiita tukemaan yksityisyyttä parantavia teknologioita. Toivomme, että käyttäjätietojen myymiseen perustuvat liiketoimintamallit jäävät lopulta menneeseen.<br><br>Lopuksi, tarjoamme suurimman osan CryptPadin toiminnallisuudesta ilmaiseksi, koska uskomme yksityisyyden kuuluvan kaikille - ei vain niille, joilla on varaa maksaa siitä. Tukemalla meitä autat tarjoamaan heikommassa asemassa oleville väestöille pääsyn näihin peruspalveluihin."
"a": "Annamme tukijoillemme lisätallennustilaa ja mahdollisuuden kasvattaa yhteystietojen tallennustilakiintiöitä (<a href='https://accounts.cryptpad.fr/#/faq' target='_blank'>lue lisää</a>).<br><br>Näiden lyhytaikaisten etujen lisäksi premium-tilaus auttaa rahoittamaan CryptPadin jatkuvaa, aktiivista kehitystyötä. Tähän kuuluu bugien korjaamista, uusien ominaisuuksien lisäämistä ja CryptPad-instanssien pystyttämisen ja ylläpidon helpottamista. Lisäksi autat näyttämään muille palveluntarjoajille, että ihmiset ovat valmiita tukemaan yksityisyyttä parantavia teknologioita. Toivomme, että käyttäjätietojen myymiseen perustuvat liiketoimintamallit jäävät lopulta menneeseen.<br><br>Lopuksi, tarjoamme suurimman osan CryptPadin toiminnallisuudesta ilmaiseksi, koska uskomme yksityisyyden kuuluvan kaikille - ei vain niille, joilla on varaa maksaa siitä. Tukemalla meitä autat tarjoamaan heikommassa asemassa oleville väestöille pääsyn näihin peruspalveluihin."
},
"goal": {
"q": "Mitkä ovat tavoitteenne?",
@ -1018,20 +1018,20 @@
"help": {
"title": "Näin pääset alkuun",
"generic": {
"more": "Tutustu <a href=\"/faq.html\" target=\"_blank\">usein kysyttyihin kysymyksiin</a> saadaksesi lisätietoja CryptPadin toiminnallisuudesta",
"share": "Käytä Jaa-valikkoa (<span class=\"fa fa-shhare-alt\"></span>) luodaksesi linkin, jonka kautta yhteistyökumppanit pääsevät katselemaan tai muokkaamaan padia",
"more": "Tutustu <a href=\"/faq.html\" target=\"_blank\">usein kysyttyihin kysymyksiin</a> saadaksesi lisätietoja CryptPadin toiminnallisuudesta.",
"share": "Jaa tämä asiakirja <i class=\"fa fa-shhare-alt\"></i> <b>Jaa</b>-painikkeella ja hallitse käyttöoikeuksia <i class=\"fa fa-unlock-alt\"></i> <b>Käyttöoikeudet</b>-painikkeella.",
"save": "Kaikki tekemäsi muutokset synkronoidaan automaattisesti, joten sinun ei tarvitse koskaan tallentaa"
},
"text": {
"formatting": "Voit näyttää tai piilottaa Tekstin muotoilu-työkalupalkin klikkaamalla <span class=\"fa fa-caret-down\"></span> tai <span class=\"fa fa-caret-up\"></span>-painikkeita",
"embed": "Rekisteröityneet käyttäjät voivat upottaa kuvan tai CryptDriveen tallennetun tiedoston <span class=\"fa fa-image\"></span> avulla",
"formatting": "Näytä tai piilota tekstityökalupalkki <i class=\"fa fa-wrench\"></i> <b>Työkalut</b>-painikkeella.",
"embed": "Upota kuvatiedosto CryptDrivestasi tai tietokoneeltasi <i class=\"fa fa-image\"></i> <b>Upota</b>-painikkeella (vain rekisteröityneille käyttäjille).",
"history": "Voit käyttää <em>historiaa</em> <span class=\"fa fa-history\"></span> katsellaksesi tai palauttaaksesi aiempia versioita"
},
"pad": {
"export": "Voit viedä sisältösi PDF-tiedostoon Tekstin muotoilu-työkalupalkin <span class=\"fa fa-print\"></span> -painikkeella"
},
"code": {
"modes": "Käytä <span class=\"fa fa-ellipsis-h\"></span> -alavalikon pudotusvalikoita vaihtaaksesi syntaksin korostustilaa tai väriteemoja"
"modes": "Käytä <span class=\"cptools cptools-palette\"></span> <b>Teema</b> -valikkoa valitaksesi editorin teeman ja syntaksin korostustilan."
},
"beta": {
"warning": "Tämä editori on edelleen <strong>koekäytössä</strong>, voit ilmoittaa löytämäsi bugit <a href=\"https://github.com/xwiki-labs/cryptpad/issues/\" target=\"_blank\">asianhallintajärjestelmäämme</a>"
@ -1042,27 +1042,367 @@
"slide": {
"markdown": "Kirjoita diat <a href=\"http://www.markdowntutorial.com/\">Markdown-kielellä</a> ja erota ne toisistaan <code>---</code> -rivillä",
"present": "Aloita esitys <span class=\"fa fa-play-circle\"></span> -painikkeella",
"settings": "Muuta dian asetuksia (taustakuvaa, siirtymiä, sivunumeroita jne.) <span class=\"fa fa-ellipsis-h\"></span> -alavalikon <span class=\"fa fa-cog\"></span> -painikkeella",
"settings": "Käytä <span class=\"cptools cptools-palette\"></span> <b>Teema</b>-valikkoa vaihtaaksesi diavärejä ja <span class=\"fa fa-cog\"></span> <b>Asetukset</b> vaihtaaksesi taustakuvaa, siirtymiä, sivunumeroita jne.",
"colors": "Vaihda tekstin ja taustan väriä <span class=\"fa fa-i-cursor\"></span> ja <span class=\"fa fa-square\"></span> -painikkeilla"
},
"poll": {
"decisions": "Tee päätöksiä luotettujen kontaktien kesken",
"decisions": "Tee päätöksiä luotettujen yhteystietojen kanssa",
"options": "Ehdota vaihtoehtoja ja tuo ilmi mielipiteesi",
"choices": "Napsauta sarakkeesi soluja valitaksesi kyllä- (<strong>✔</strong>), ehkä- (<strong>~</strong>), tai ei (<strong>✖</strong>) -vaihtoehdon",
"submit": "Napsauta <strong>Lähetä</strong> tehdäksesi valintasi näkyviksi muille"
},
"whiteboard": {
"colors": "Kaksoisnapsauta värejä muokataksesi väripalettiasi",
"mode": "Ota piirtotila pois käytöstä vetääksesi ja venyttääksesi viivoja",
"embed": "Upota kuvia kovalevyltäsi <span class=\"fa fa-file-image-o\"></span> tai CryptDrivestasi <span class=\"fa fa-image\"></span> ja vie ne PNG-tiedostomuodossa kovalevyllesi <span class=\"fa fa-download\"></span> tai CryptDriveesi <span class=\"fa fa-cloud-upload\"></span>"
"mode": "Siirry <span class=\"fa fa-arrows\"></span> valintatilaan siirtääksesi ja muuttaaksesi viivoja.",
"embed": "Upota kuvia CryptDrivestasi tai tietokoneeltasi <span class=\"fa fa-file-image-o\"></span> <b>Lisää</b>-toiminnolla. Vie kangas PNG-tiedostomuodossa CryptDriveesi <b><span class=\"fa fa-file-o\"></span> Tiedosto > <span class=\"fa fa-file-image-o\"></span> Tallenna kuvatiedostona</b> tai omalle tiedokoneellesi <b><span class=\"fa fa-file-o\"></span> Tiedosto > <span class=\"fa fa-download\"></span> Vie</b>."
},
"kanban": {
"add": "Lisää uusia kortteja ja tauluja <span class=\"fa fa-plus\"></span> -painikkeella",
"add": "Lisää uusia kortteja ja tauluja <span class=\"fa fa-plus\"></span> -painikkeella",
"task": "Siirrä kohtia raahaamalla ja pudottamalla, raahaa <span class=\"fa fa-trash\"></span> roskakoriin poistaaksesi",
"color": "Muokkaa otsikoita, sisältöä, tunnisteita ja värejä korttien ja taulujen otsikoiden vieressä olevalla span class=\"fa fa-pencil\"></span> -painikkeella"
"color": "Muokkaa otsikoita, sisältöä, tunnisteita ja värejä korttien ja taulujen otsikoiden vieressä olevalla <span class=\"fa fa-pencil\"></span> -painikkeella"
}
},
"driveReadmeTitle": "Mikä on CryptPad?",
"readme_welcome": "Tervetuloa CryptPadiin!",
"readme_p1": "Tervetuloa CryptPadiin, täällä voit tehdä muistiinpanoja yksin tai kontaktiesi kanssa."
"readme_p1": "Tervetuloa CryptPadiin, täällä voit tehdä muistiinpanoja yksin tai yhteystietojesi kanssa.",
"settings_kanbanTagsOr": "TAI",
"settings_kanbanTagsAnd": "JA",
"settings_kanbanTagsHint": "Valitse, miten haluat tunnistesuodattimen toimivan useita tunnisteita käytettäessä: näytä kortit, jotka sisältävät kaikki valitut tunnisteet (JA) tai näytä kortit, jotka sisältävät jonkun tai jotkin valituista tunnisteista (TAI)",
"settings_kanbanTagsTitle": "Tunnistesuodatin",
"pad_tocHide": "Hahmotelma",
"fm_noResult": "Ei tuloksia",
"fm_restricted": "Sinulla ei ole käyttöoikeutta",
"fm_emptyTrashOwned": "Roskakori sisältää omistamiasi asiakirjoja. Voit <b>poistaa</b> ne omasta CryptDrivestasi tai <b>tuhota</b> ne kaikilta käyttäjiltä.",
"support_formCategoryError": "Virhe: kategoria on tyhjä",
"support_category": "Valitse kategoria",
"oo_refreshText": "Tämä asiakirja on päivitetty",
"oo_refresh": "Päivitä",
"notification_folderSharedTeam": "{0} on jakanut tiimin {2} kanssa kansion: <b>{1}</b>",
"notification_fileSharedTeam": "{0} on jakanut tiimin {2} kanssa tiedoston: <b>{1}</b>",
"notification_padSharedTeam": "{0} on jakanut tiimin {2} kanssa padin: <b>{1}</b>",
"support_addAttachment": "Lisää liite",
"support_attachments": "Liitteet",
"support_cat_all": "Kaikki",
"support_cat_other": "Muu",
"support_cat_bug": "Virheraportti",
"support_cat_data": "Sisällön katoaminen",
"support_cat_account": "Käyttäjätili",
"info_privacyFlavour": "<a>Tietosuojakäytäntömme</a> kertoo, miten kohtelemme tietojasi.",
"user_about": "Tietoja CryptPadista",
"info_imprintFlavour": "<a>Oikeudellisia tietoja tämän instanssin ylläpitäjistä</a>.",
"settings_safeLinkDefault": "Turvalliset linkit on nyt otettu käyttöön oletusarvoisesti. Käytä <i class=\"fa fa-shhare-alt\"></i> <b>Jaa</b>-valikkoa linkkien kopiointiin selaimesi osoiterivin sijaan.",
"support_languagesPreamble": "Tukitiimi puhuu seuraavia kieliä:",
"slide_textCol": "Tekstin väri",
"slide_backCol": "Taustaväri",
"toolbar_file": "Tiedosto",
"code_editorTheme": "Editoriteema",
"drive_treeButton": "Tiedostot",
"toolbar_tools": "Työkalut",
"toolbar_savetodrive": "Tallenna kuvatiedostona",
"toolbar_insert": "Lisää",
"toolbar_theme": "Teema",
"todo_move": "Tehtäväluettelosi on nyt kanbanissa <b>{0}</b> CryptDrivessasi.",
"fm_sort": "Lajittele",
"comments_error": "Kommentin lisääminen ei onnistu tähän",
"settings_padNotifCheckbox": "Ota kommentti-ilmoitukset pois käytöstä",
"settings_padNotifHint": "Jätä huomioitta ilmoitukset, kun joku vastaa kommentteihisi",
"settings_padNotifTitle": "Kommentti-ilmoitukset",
"comments_comment": "Kommentoi",
"comments_resolve": "Ratkaise",
"comments_reply": "Vastaa",
"comments_submit": "Lähetä",
"comments_edited": "Muokattu",
"comments_deleted": "Tekijän poistama kommentti",
"mentions_notification": "{0} on maininnut sinut <b>{1}</b>",
"unknownPad": "Tuntematon padi",
"comments_notification": "Vastaukset kommenttiisi \"{0}\" <b>{1}</b>",
"cba_title": "Tekijäkohtaiset värit",
"pad_usePageWidth": "Sivutila",
"pad_useFullWidth": "Täyden leveyden tila",
"oo_login": "Kirjaudu sisään tai rekisteröidy parantaaksesi taulukoiden suorituskykyä.",
"cba_hide": "Piilota tekijäkohtaiset värit",
"cba_show": "Näytä tekijäkohtaiset värit",
"cba_disable": "Tyhjennä ja poista käytöstä",
"cba_enable": "Ota käyttöön",
"cba_hint": "Tämä asetus muistetaan seuraavan padin luonnin yhteydessä.",
"cba_properties": "Tekijäkohtaiset värit (kokeellinen)",
"cba_writtenBy": "Kirjoittaja: {0}",
"canvas_select": "Valinta",
"canvas_brush": "Sivellin",
"admin_openFilesHint": "Palvelimella olevien avoimien tiedostokahvojen määrä.",
"admin_openFilesTitle": "Avoimet tiedostot",
"profile_copyKey": "Kopioi julkinen avain",
"oo_isLocked": "synkronoidaan muutoksia, odota",
"kanban_editBoard": "Muokkaa tätä taulua",
"kanban_editCard": "Muokkaa tätä korttia",
"kanban_clearFilter": "Tyhjennä suodatin",
"kanban_conflicts": "Muokkaamassa:",
"kanban_noTags": "Ei tunnisteita",
"kanban_tags": "Suodata tunnisteella",
"kanban_delete": "Poista",
"kanban_color": "Väri",
"kanban_title": "Otsikko",
"teams": "Tiimit",
"allow_text": "Käyttölista tarkoittaa, että vain valitut käyttäjät ja omistajat pääsevät käyttämään tätä asiakirjaa.",
"owner_text": "Padin omistajat ovat ainoita käyttäjiä, jotka saavat lisätä/poistaa omistajia, rajoittaa padin käyttöä käyttölistalla tai poistaa padin.",
"access_muteRequests": "Vaimenna tämän padin käyttöpyynnöt",
"allow_label": "Käyttölista: {0}",
"allow_disabled": "pois käytöstä",
"allow_enabled": "käytössä",
"allow_checkbox": "Ota käyttöön käyttölista",
"access_noContact": "Ei lisättäviä yhteystietoja",
"contacts": "Yhteystiedot",
"accessButton": "Käyttöoikeudet",
"access_allow": "Lista",
"access_main": "Käyttöoikeudet",
"copy_title": "{0} (kopio)",
"makeACopy": "Tee kopio",
"settings_trimHistoryHint": "Säästä tallennustilaa poistamalla CryptDrivesi historia ja ilmoitukset. Tämä ei vaikuta padiesi historiaan. Voit poistaa padien historian niiden Ominaisuudet-ikkunasta.",
"settings_trimHistoryTitle": "Poista historiatiedot",
"trimHistory_noHistory": "Ei poistettavia historiatietoja",
"trimHistory_currentSize": "Nykyinen historiakoko: <b>{0}</b>",
"trimHistory_needMigration": "Ole hyvä ja <a>päivitä CryptDrivesi</a> käyttääksesi tätä toimintoa.",
"trimHistory_success": "Historiatiedot on poistettu",
"trimHistory_error": "Virhe historiatietoja poistettaessa",
"trimHistory_getSizeError": "Virhe CryptDriven historian kokoa laskettaessa",
"trimHistory_button": "Poista historiatiedot",
"historyTrim_contentsSize": "SIsältö: {0}",
"historyTrim_historySize": "Historia: {0}",
"areYouSure": "Oletko varma?",
"settings_safeLinksHint": "CryptPad sisällyttää padien avaamiseen tarvittavat avaimet niiden linkkeihin. Kuka tahansa selaushistoriaasi katseleva voi mahdollisesti päästä käsiksi tietoihisi. Tämä sisältää urkkivat selainlaajennukset ja selaushistorian usealle laitteelle synkronoivat selaimet. Turvallisten linkkien käyttöönotto estää linkkien tallentumisen selaushistoriaan tai niiden näyttämisen selaimen osoitepalkissa silloin, kun se on mahdollista. Suosittelemme tämän toiminnon käyttöönottoa ja {0} Jaa-valikon käyttöä.",
"profile_login": "Kirjaudu sisään lisätäksesi tämän käyttäjän yhteystietoihisi",
"dontShowAgain": "Älä näytä uudestaan",
"settings_safeLinksCheckbox": "Ota käyttöön turvalliset linkit",
"settings_safeLinksTitle": "Turvalliset linkit",
"settings_cat_security": "Luottamuksellisuus",
"imprint": "Oikeudellinen huomautus",
"oo_sheetMigration_anonymousEditor": "Taulukon muokkaaminen on poistettu käytöstä anonyymeille käyttäjille, kunnes rekisteröitynyt käyttäjä päivittää sen viimeisimpään versioon.",
"oo_sheetMigration_complete": "Päivitetty versio saatavilla, paina OK ladataksesi uudelleen.",
"oo_sheetMigration_loading": "Päivitetään taulukkoasi viimeisimpään versioon",
"oo_exportInProgress": "Vienti menossa",
"oo_importInProgress": "Tuonti menossa",
"oo_invalidFormat": "Tätä tiedostoa ei voida tuoda",
"oo_exportChrome": "Microsoft Office-tiedostomuotoihin muuntaminen on tällä hetkellä saatavilla ainoastaan Google Chrome-selaimessa.",
"burnAfterReading_warningDeleted": "Tämä padi on poistettu pysyvästi. Kun suljet tämän ikkunan, et pääse enää käyttämään sitä.",
"burnAfterReading_proceed": "katsele ja poista",
"burnAfterReading_generateLink": "Napsauta allaolevaa painiketta luodaksesi linkin.",
"burnAfterReading_warningLink": "Olet laittanut tämän padin itsetuhotilaan. Kun vastaanottaja avaa tämän linkin, hän voi katsella padia kerran, jonka jälkeen se poistetaan pysyvästi.",
"burnAfterReading_linkBurnAfterReading": "Katso kerran ja tuhoudu",
"fc_noAction": "Ei saatavilla olevia toimintoja",
"support_closed": "Tämä palvelupyyntö on suljettu",
"support_from": "<b>Lähettäjä:</b> {0}",
"support_showData": "Näytä/piilota käyttäjätiedot",
"support_remove": "Poista palvelupyyntö",
"support_close": "Sulje palvelupyyntö",
"support_answer": "Vastaa",
"support_listHint": "Tässä on lista ylläpitäjille lähetetyistä palvelupyynnöistä ja niiden vastauksista. Suljettua palvelupyyntöä ei voida avata uudelleen, mutta voit luoda uuden. Voit piilottaa suljetut palvelupyynnöt.",
"support_listTitle": "Tukipalvelupyynnöt",
"support_cat_tickets": "Olemassaolevat palvelupyynnöt",
"support_formMessage": "Kirjoita viestisi...",
"support_formContentError": "Virhe: sisältö on tyhjä",
"support_formTitleError": "Virhe: otsikko on tyhjä",
"support_formButton": "Lähetä",
"support_formHint": "Tällä lomakkeella voit luoda uuden palvelupyynnön. Käytä sitä ottaaksesi ylläpitäjiin yhteyttä ongelmatilanteissa tai kysyäksesi kysymyksiä turvallisella tavalla. Älä luo uutta palvelupyyntöä, jos olet jo luonut palvelupyynnön samasta ongelmasta, vaan käytä vastauspainiketta antaaksesi lisätietoja.",
"support_formTitle": "Uusi palvelupyyntö",
"support_cat_new": "Uusi palvelupyyntö",
"support_disabledHint": "Tätä CryptPad-instanssia ei ole konfiguroitu tukilomaketta varten.",
"support_disabledTitle": "Tuki ei ole käytössä",
"admin_supportListHint": "Tässä on lista käyttäjien tukipostilaatikkoon lähettämistä palvelupyynnöistä. Kaikki ylläpitäjät voivat nähdä viestit ja niiden vastaukset. Suljettua palvelupyyntöä ei voida avata uudelleen. Voit ainoastaan poistaa (piilottaa) suljettuja palvelupyyntöjä. Muut ylläpitäjät näkevät edelleen poistetut palvelupyynnöt.",
"admin_supportListTitle": "Tukipostilaatikko",
"admin_supportInitHint": "Voit konfiguroida tukipostilaatikon CryptPad-instanssisi käyttäjiltä ongelmatilanteissa tulevia tukipyyntöjä varten.",
"admin_supportInitTitle": "Tukipostilaatikon alustaminen",
"admin_supportAddError": "Virheellinen yksityinen avain",
"admin_supportAddKey": "Lisää yksityinen avain",
"admin_supportInitPrivate": "CryptPad-instanssisi on konfiguroitu käyttämään ylläpitopostilaatikkoa, mutta käyttäjätililläsi ei ole sen käyttöön tarvittavaa yksityistä avainta. Käytä seuraavaa lomaketta lisätäksesi tai päivittääksesi yksityinen avain.",
"admin_supportInitHelp": "Palvelimellesi ei ole asetettu ylläpitopostilaatikkoa. Jos haluat ottaa käyttöön ylläpitopostilaatikon käyttäjiltä tulevia viestejä varten, pyydä palvelimen ylläpitäjää ajamaan skripti \"./scripts/generate-admin-keys.js\", laittamaan skriptin generoima julkinen avain \"config.js\"-tiedostoon ja lähettämään sinulle yksityinen avain.",
"admin_cat_support": "Tuki",
"supportPage": "Tuki",
"share_description": "Valitse, mitä haluat jakaa ja luo jakolinkki tai jaa suoraan CryptPad-yhteystiedoillesi.",
"fm_info_sharedFolderHistory": "Tämä on jaetun kansiosi historia: <b>{0}</b><br/>CryptDrivesi pysyy vain luku-tilassa selatessasi sitä.",
"notifications_dismiss": "Hylkää",
"share_withFriends": "Jaa",
"share_linkFriends": "Jaa yhteystietojen kanssa",
"share_filterFriend": "Hae nimen perusteella",
"share_deselectAll": "Poista valinta",
"share_selectAll": "Valitse kaikki",
"notification_folderShared": "{0} on jakanut kanssasi kansion: <b>{1}</b>",
"notification_fileShared": "{0} on jakanut kanssasi tiedoston: <b>{1}</b>",
"notification_padShared": "{0} on jakanut kanssasi padin: <b>{1}</b>",
"isNotContact": "{0} <b>ei</b> ole yhteystiedoissasi",
"isContact": "{0} on yhteystiedoissasi",
"profile_friendRequestSent": "Yhteyspyyntö odottaa...",
"profile_addLink": "Lisää linkki kotisivullesi",
"profile_editDescription": "Muokkaa kuvaustasi",
"profile_addDescription": "Lisää kuvaus",
"notifications_title": "Sinulla on lukemattomia ilmoituksia",
"notifications_empty": "Ei ilmoituksia saatavilla",
"friendRequest_notification": "<b>{0}</b> lähetti sinulle yhteyspyynnön",
"friendRequest_received": "<b>{0}</b> haluaisi olla yhteystietosi",
"friendRequest_accepted": "<b>{0}</b> hyväksyi yhteyspyyntösi",
"friendRequest_declined": "<b>{0}</b> kieltäytyi yhteyspyynnöstäsi",
"friendRequest_decline": "Kieltäydy",
"friendRequest_accept": "Hyväksy (Enter)",
"friendRequest_later": "Päätä myöhemmin",
"drive_activeOld": "Vanhemmat padit",
"drive_active28Days": "Viimeiset 4 viikkoa",
"drive_active7Days": "Viimeiset 7 päivää",
"drive_active1Day": "Viimeiset 24 tuntia",
"settings_codeSpellcheckLabel": "Ota oikeinkirjoituksen tarkistus käyttöön koodieditorissa",
"settings_codeSpellcheckTitle": "Oikeinkirjoituksen tarkistus",
"admin_diskUsageButton": "Luo raportti",
"admin_diskUsageHint": "CryptPad-resurssien käyttämä tallennustila",
"admin_diskUsageTitle": "Tallennustilan käyttö",
"timeoutError": "Virhe on katkaissut yhteytesi palvelimelle. <br> Paina <em>Esc</em> ladataksesi sivun uudelleen.",
"contact_email": "Sähköposti",
"contact_chat": "Keskustelu",
"contact_bug": "Virheraportti",
"contact_devHint": "Ominaisuuspyyntöjä, käytettävyysparannuksia tai kiitoksia varten.",
"contact_dev": "Ota yhteyttä kehittäjiin",
"contact_adminHint": "Käyttäjätiliin, tallennustilaan tai palvelun saatavuuteen liittyviä ongelmia varten.",
"contact_admin": "Ota yhteyttä ylläpitäjiin",
"footer_tos": "Käyttöehdot",
"footer_legal": "Oikeusasiat",
"footer_donate": "Lahjoita",
"footer_team": "Tiimimme",
"footer_product": "Tuotteemme",
"admin_flushCacheDone": "Välimuisti tyhjennetty onnistuneesti",
"admin_flushCacheButton": "Tyhjennä välimuisti",
"admin_flushCacheHint": "Pakota käyttäjät lataamaan uusimmat asiakassovelluksen osat (ainoastaan jos palvelimesi on fresh modessa)",
"adminPage": "Ylläpito",
"admin_cat_stats": "Tilastotiedot",
"admin_cat_general": "Yleiset asetukset",
"admin_authError": "Vain ylläpitäjät pääsevät tälle sivulle",
"fm_expirablePad": "Vanhenee: {0}",
"markdown_toc": "Sisältö",
"survey": "CryptPad-kysely",
"crowdfunding_popup_no": "Ei nyt",
"crowdfunding_popup_yes": "Mene OpenCollectiveen",
"crowdfunding_popup_text": "<h3>Tarvitsemme apuasi!</h3>Haluatko tukea CryptPadin aktiivista kehitystä? Harkitse projektin tukemista <a href=\"https://opencollective.com/cryptpad\">OpenCollective-sivullamme</a>, jossa voit nähdä <b>tiekarttamme</b> ja <b>rahoitustavoitteemme</b>.",
"crowdfunding_button2": "Auta CryptPadia",
"crowdfunding_button": "Tue CryptPadia",
"crowdfunding_home2": "Napsauta painiketta saadaksesi lisätietoja joukkorahoituskampanjastamme.",
"crowdfunding_home1": "CryptPad tarvitsee apuasi!",
"autostore_notAvailable": "Sinun täytyy tallentaa tämä padi CryptDriveesi käyttääksesi tätä toimintoa.",
"autostore_forceSave": "Tallenna tiedosto CryptDriveesi",
"autostore_saved": "Padi tallennettiin onnistuneesti CryptDriveesi!",
"autostore_error": "Odottamaton virhe: emme voineet tallentaa padia, ole hyvä ja yritä uudestaan.",
"autostore_hide": "Älä tallenna",
"autostore_store": "Tallenna",
"autostore_settings": "Voit ottaa automaattisen padien tallennuksen käyttöön <a href=\"/settings/\">Asetukset</a>-sivulta!",
"autostore_notstored": "Tämä {0} ei ole tallennettuna CryptDrivessasi. Haluatko tallentaa sen nyt?",
"autostore_pad": "padi",
"autostore_sf": "kansio",
"autostore_file": "tiedosto",
"chrome68": "Näyttää, että käytät Chrome- tai Chromium-selaimen versiota 68. Siinä on bugi, joka saattaa muuttaa sivun valkoiseksi tai estää sivua reagoimasta napsautuksiin. Korjataksesi ongelman voit siirtyä toiseen välilehteen ja siirtyä takaisin tai vaihtoehtoisesti vierittää sivua. Bugin tulisi olla korjattu selaimesi seuraavassa versiossa.",
"convertFolderToSF_confirm": "Tämä kansio täytyy muuttaa jaetuksi kansioksi, jotta muut voivat katsella sitä. Jatketaanko?",
"convertFolderToSF_SFChildren": "Tätä kansiota ei voida muuttaa jaetuksi kansioksi, sillä se sisältää ennestään jaettuja kansioita. Siirrä jaetut kansiot muualle jatkaaksesi.",
"convertFolderToSF_SFParent": "Tätä kansiota ei voida muuttaa jaetuksi kansioksi sen nykyisessä sijainnissa. Siirrä se nykyisen jaetun kansion ulkopuolelle jatkaaksesi.",
"sharedFolders_share": "Jaa tämä linkki muiden rekisteröityneiden käyttäjien kanssa antaaksesi heille pääsyn jaettuun kansioon. Kun linkki avataan, lisätään jaettu kansio heidän CryptDriveihinsa.",
"sharedFolders_create_password": "Kansion salasana",
"sharedFolders_create_owned": "Omistettu kansio",
"sharedFolders_create_name": "Kansion nimi",
"sharedFolders_create": "Luo jaettu kansio",
"sharedFolders_duplicate": "Jotkin padeista, joita yritit siirtää olivat jo jaettuja kohdekansiossa.",
"sharedFolders_forget": "Tämä padi on tallennettu ainoastaan jaettuun kansioon, et voi siirtää sitä roskakoriin. Voit käyttää CryptDriveasi sen poistamiseen.",
"loading_drive_3": "Tarkistetaan tietojen eheyttä",
"loading_drive_2": "Päivitetään tietomuotoa",
"loading_drive_1": "Ladataan tietoja",
"loading_pad_2": "Ladataan padin sisältöä",
"loading_pad_1": "Alustetaan padia",
"share_mediatagCopy": "Kopioi mediatunniste leikepöydälle",
"share_embedCategory": "Upota",
"share_contactCategory": "Yhteystiedot",
"share_linkCopy": "Kopioi",
"share_linkOpen": "Esikatsele",
"share_linkPresent": "Nykyinen",
"share_linkEmbed": "Upotettu tila (piilota työkalupalkki ja käyttäjälista)",
"share_linkView": "Katsele",
"share_linkEdit": "Muokkaa",
"share_linkAccess": "Käyttöoikeudet",
"share_linkCategory": "Linkki",
"properties_changePasswordButton": "Lähetä",
"properties_passwordSuccess": "Salasana vaihdettiin onnistuneesti.<br>Napsauta OK ladataksesi sivu uudelleen ja päivittääksesi käyttöoikeudet.",
"properties_passwordWarning": "Salasana vaihdettiin onnistuneesti, mutta emme voineet päivittää CryptDriveasi uusilla tiedoilla. Joudut ehkä poistamaan padin vanhan version manuaalisesti.<br>Napsauta OK ladataksesi sivu uudelleen ja päivittääksesi käyttöoikeudet.",
"properties_passwordError": "Salasanan vaihtamisessa tapahtui virhe. Ole hyvä ja yritä uudelleen.",
"properties_passwordSame": "Uuden salasanan täytyy erota nykyisestä salasanasta.",
"properties_confirmNew": "Oletko varma? Salasanan lisääminen muuttaa padin URL-osoitteen ja poistaa sen historiatiedot. Käyttäjät, joilla ei ole salasanaa eivät enää pääse käyttämään padia",
"properties_confirmChange": "Oletko varma? Salasanan vaihtaminen poistaa sen historian. Käyttäjät, joilla ei ole salasanaa eivät enää pääse käyttämään padia",
"properties_changePassword": "Vaihda salasanaa",
"properties_addPassword": "Lisää salasana",
"password_show": "Näytä",
"password_submit": "Lähetä",
"password_placeholder": "Kirjoita salasana tähän...",
"password_error": "Padia ei löytynyt!<br>Tämä virhe voi johtua kahdesta syystä: joko salasana on virheellinen tai padi on poistettu palvelimelta.",
"password_info": "Padia, jota yrität avata ei ole enää olemassa tai se on suojattu salasanalla. Syötä oikea salasana käyttääksesi padin sisältöä.",
"creation_newPadModalAdvanced": "Näytä padien luontiruutu",
"creation_newPadModalDescriptionAdvanced": "Voit rastittaa valintaruudun (tai painaa <b>Välilyönti</b>-painiketta vaihtaaksesi sen arvoa), jos haluat näyttää padien luontiruudun (omistetut ja vanhenevat padit jne.).",
"creation_newPadModalDescription": "Napsauta padityyppiä luodaksesi sellainen. Voit myös painaa <b>Tab</b>-näppäintä valitaksesi tyypin ja <b>Enter</b> vahvistaaksesi valinnan.",
"creation_appMenuName": "Uusi padi (Ctrl + E)",
"creation_propertiesTitle": "Saatavuus",
"creation_passwordValue": "Salasana",
"creation_expiration": "Vanhenemisaika",
"creation_noOwner": "Ei omistajaa",
"creation_ownedByOther": "Toisen käyttäjän omistama",
"creation_owners": "Omistajat",
"creation_rememberHelp": "Käy Asetukset-sivulla nollataksesi tämän asetuksen",
"creation_settings": "Katso lisää asetuksia",
"creation_create": "Luo",
"creation_newTemplate": "Uusi mallipohja",
"creation_noTemplate": "Ei mallipohjaa",
"creation_password": "Lisää salasana",
"creation_expire2": "<b>Vanhenevalla</b> padilla on asetettu elinikä, jonka täyttyessä se poistetaan automaattisesti palvelimelta ja muiden käyttäjien CryptDriveista.",
"creation_expire1": "<b>Rajoittamatonta</b> padia ei poisteta palvelimelta, ellei sen omistaja poista sitä.",
"creation_expireMonths": "Kuukausi(a)",
"creation_expireDays": "Päiv(i)ä",
"creation_expireHours": "Tunti(a)",
"creation_expireFalse": "Rajoittamaton",
"creation_expireTrue": "Lisää elinaika",
"creation_expire": "Vanheneva padi",
"creation_expireTitle": "Elinikä",
"creation_owned2": "<b>Avoimella</b> padilla ei ole omistajaa, ja sitä ei voida poistaa palvelimelta, ellei sen vanhenemisaika ole tullut täyteen.",
"creation_owned1": "<b>Omistettu</b> padi voidaan poistaa palvelimelta omistajan niin halutessa. Omistetun padin poistaminen poistaa sen muiden käyttäjien CryptDriveista.",
"creation_ownedFalse": "Avoin padi",
"creation_ownedTrue": "Omistettu padi",
"creation_owned": "Omistettu padi",
"creation_ownedTitle": "Padin tyyppi",
"creation_404": "Tätä padia ei ole enää olemassa. Käytä seuraavaa lomaketta uuden padin luontiin.",
"feedback_optout": "Jos haluat jättäytyä pois tästä toiminnallisuudesta, voit tehdä sen <a href='/settings/'>Käyttäjäasetukset</a>-sivulta löytyvän käyttäjäpalautevalintaruudun avulla",
"feedback_privacy": "Välitämme yksityisyydestäsi, ja haluamme samalla tehdä CryptPadista mahdollisimman helppokäyttöisen. Käytämme tätä tiedostoa selvittääksemme, mitkä käyttöliittymätoiminnot ovat tärkeitä käyttäjillemme, pyytämällä sitä tehdyn toiminnon kertovan parametrin yhteydessä.",
"feedback_about": "Jos luet tätä, haluat todennäköisesti tietää, miksi CryptPad lähettää pyyntöjä web-sivuille tiettyjen toimintojen yhteydessä",
"tips": {
"tags": "Lisää padeihisi tunnisteita ja aloita haku #-merkillä CryptDrivessasi löytääksesi ne tunnisteen perusteella",
"avatars": "Voit ladata käyttäjäprofiiliisi avatar-kuvan. Muut padia kanssasi käyttävät henkilöt näkevät sen.",
"profile": "Rekisteröityneet käyttäjät voivat luoda käyttäjäprofiilin oikeasta yläkulmasta löytyvästä käyttäjävalikosta.",
"drive": "Sisäänkirjautuneet käyttäjät voivat järjestellä CryptDriveen tallennettuja tiedostoja napsauttamalla kaikkien padien vasemmassa yläkulmassa olevaa CryptPad-kuvaketta.",
"filenames": "Voit nimetä tiedostoja uudelleen CryptDrivessasi, tämä nimi on vain sinua varten.",
"driveUpload": "Rekisteröityneet käyttäjät voivat ladata salattuja tiedostoja napsauttamalla ja raahaamalla ne omiin CryptDriveihinsa.",
"marker": "Voit korostaa padissa olevaa tekstiä käyttämällä tyylialavalikosta löytyvää huopakynää.",
"store": "Joka kerta kun käytät padia sisäänkirjautuneena, se tallennetaan CryptDriveesi.",
"indent": "Numeroiduissa luetteloissa ja luettelomerkkiluetteloissa voit käyttää Tab- tai Shift+Tab-näppäinyhdistelmiä kasvattaaksesi tai pienentääksesi sisennystä.",
"shortcuts": "`ctrl+b`, `ctrl+i` ja `ctrl+u`toimivat oikoteinä lihavoidulle, kursiiville ja alleviivatulle tekstille."
},
"readme_cat3_l3": "CryptPad-kyselyilä voit pitää nopeita äänestyksiä esimerkiksi kokouksien aikataulujen yhteensovittamiseksi",
"readme_cat3_l2": "CryptPad-diaeditorilla voit luoda nopeasti diaesityksiä Markdown-kielellä",
"readme_cat3_l1": "CryptPad-koodieditorilla voit työskennellä yhdessä muiden kanssa koodin, kuten Javascriptin ja Markdownin parissa",
"settings_cat_kanban": "Kanban",
"kanban_body": "Sisältö",
"logoutEverywhere": "Kirjaudu ulos kaikkialta",
"restrictedError": "Sinulla ei ole oikeutta käyttää tätä asiakirjaa",
"safeLinks_error": "Tämä linkki kopioitiin selaimen osoiteriviltä, eikä se anna käyttöoikeutta asiakirjaan. Ole hyvä ja käytä <i class=\"fa fa-shhare-alt\"></i> <b>Jaa</b> -valikkoa jakaaksesi yhteystietojen kanssa tai kopioidaksesi linkin. <a href=\"https://docs.cryptpad.fr/en/user_guide/user_account.html#confidentiality\"> Lue lisää Turvalliset linkit-ominaisuudesta</a>.\n",
"burnAfterReading_warningAccess": "Tämä asiakirja tuhoaa itsensä. Kun napsautat allaolevaa painiketta, näet sisällön kerran, jonka jälkeen se poistetaan pysyvästi. Kun suljet tämän ikkunan, et pääse enää käyttämään asiakirjan sisältöä. Jos et ole valmis jatkamaan, voit sulkea tämän ikkunan ja tulla myöhemmin takaisin.",
"profile_info": "Muut käyttäjät voivat löytää käyttäjäprofiilisi asiakirjojen käyttäjälistoissa näkyvän avatarin avulla.",
"readme_cat3": "Löydä CryptPad-sovellukset",
"readme_cat2_l2": "Vaihda padin otsikkoa napsauttamalla lyijykynää",
"readme_cat2_l1": "Padistasi löytyvä {0}-painike antaa sinun jakaa yhteistyökumppaneillesi oikeuden [1} tai {2} padia.",
"edit": "muokata",
"view": "katsella",
"readme_cat2": "Luo padeja kuin ammattilainen",
"readme_cat1_l4": "Laita vanhat padit roskakoriin: Voit napsauttaa ja raahata padeja {0}in samalla tavalla kuin raahaisit niitä kansioihin.",
"readme_cat1_l3_l2": "Muista kokeilla hiiren oikeaa painiketta kuvakkeiden päällä, sillä niistä aukeaa usein lisävalikoita.",
"readme_cat1_l3_l1": "Voit napsauttaa ja raahata tiedostoja kansioihin CryptDrivesi {0}-osiossa ja luoda uusia kansioita.",
"readme_cat1_l3": "Järjestele padejasi: Kun olet kirjautuneena sisään, kaikki käyttämäsi padit näytetään CryptDrivesi {0}-osiossa.",
"readme_cat1_l2": "Avaa padeja CryptDrivestasi: kaksoisnapsauta padin kuvaketta avataksesi sen.",
"readme_cat1_l1": "Luo padi: Siirry CryptDriveesi, napsauta {0} ja sitten {1}, ja voit luoda padin.",
"readme_cat1": "Tutustu CryptDriveesi",
"readme_p2": "Tämä padi toimii pikaisena perehdytyksenä CryptPadin ominaisuuksiin - kuinka tehdä muistiinpanoja, järjestellä niitä ja tehdä yhteistyötä niiden parissa."
}

View File

@ -349,7 +349,7 @@
"fm_info_recent": "Ces pads ont été récemment ouverts ou modifiés par vous ou vos collaborateurs.",
"fm_info_trash": "Vider la corbeille permet de libérer de l'espace dans votre CryptDrive.",
"fm_info_allFiles": "Contient tous les fichiers de \"Documents\", \"Fichiers non triés\" et \"Corbeille\". Vous ne pouvez pas supprimer ou déplacer des fichiers depuis cet endroit.",
"fm_info_anonymous": "Vous n'êtes pas connecté, ces pads seront donc supprimés après 3 mois d'inactivité (<a href=\"https://blog.cryptpad.fr/2017/05/17/You-gotta-log-in/\" target=\"_blank\">découvrez pourquoi</a>). Ils sont stockés dans votre navigateur donc nettoyer votre historique peut les faire disparaître.<br><a href=\"/register/\">Inscrivez-vous</a> ou <a href=\"/login/\">connectez-vous</a> pour les maintenir en vie.<br>",
"fm_info_anonymous": "Vous n'êtes pas connecté, ces documents seront donc supprimés après {0} jours. Nettoyer l'historique de votre navigateur peut les faire disparaître.<br><a href=\"/register/\">Enregistrez vous</a> (aucune information personelle requise) ou <a href=\"/login/\">Connectez vous</a> pour les stocker de manière permanente dans votre drive. <a href=\"https://docs.cryptpad.fr/fr/user_guide/user_account.html#account-types\" target=\"_blank\">En lire plus sur les comptes utilisateurs</a>.",
"fm_info_sharedFolder": "Voici le contenu d'un dossier partagé. Il n'est accessible qu'en lecture seule car vous n'êtes pas connecté.<br><a href=\"/register/\">Inscrivez-vous</a> ou <a href=\"/login/\">connectez-vous</a> pour pouvoir l'importer dans votre CryptDrive et le modifier.",
"fm_info_owned": "Vous êtes propriétaire des pads affichés dans cette catégorie. Cela signifie que vous pouvez choisir de les supprimer définitivement du serveur à n'importe quel moment. Ils seront alors inaccessibles pour tous les autres utilisateurs.",
"fm_alert_backupUrl": "Lien de secours pour ce CryptDrive.<br>Il est <strong>fortement recommandé</strong> de garder ce lien pour vous-même.<br>Il vous servira en cas de perte des données de votre navigateur afin de retrouver vos fichiers.<br>Quiconque se trouve en possession de celui-ci peut modifier ou supprimer tous les fichiers de ce gestionnaire.<br>",
@ -1293,7 +1293,7 @@
"settings_safeLinksHint": "CryptPad inclut dans ses liens les clés permettant de déchiffrer vos pads. Toute personne ayant accès à votre historique de navigation peut potentiellement lire vos données. Cela inclut les extensions de navigateur intrusives et les navigateurs qui synchronisent votre historique entre les appareils. L'activation des \"liens sécurisés\" empêche les clés d'entrer dans votre historique de navigation ou d'être affichées dans votre barre d'adresse quand cela est possible. Nous vous recommandons vivement d'activer cette fonction et d'utiliser le menu {0} Partager.",
"profile_login": "Vous devez vous connecter pour ajouter cet utilisateur à vos contacts",
"dontShowAgain": "Ne plus demander",
"safeLinks_error": "Le lien utilisé ne permet pas d'ouvrir ce document",
"safeLinks_error": "Ce lien a été copié depuis la barre d'addresse du navigateur et ne donne pas accès au document. Veuillez utiliser le menu <i class=\"fa fa-shhare-alt\"></i> <b>Partager</b> pour partager avec vos contacts ou copier un lien. <a href=\"https://docs.cryptpad.fr/fr/user_guide/user_account.html#confidentiality\"> En savoir plus sur les Liens Sécurisés</a>.\n",
"settings_safeLinksCheckbox": "Activer les liens sécurisés",
"settings_safeLinksTitle": "Liens Sécurisés",
"settings_cat_security": "Confidentialité",

View File

@ -356,7 +356,7 @@
"fm_info_recent": "These pads have recently been opened or modified by you or people you collaborate with.",
"fm_info_trash": "Empty your trash to free space in your CryptDrive.",
"fm_info_allFiles": "Contains all the files from \"Documents\", \"Unsorted\" and \"Trash\". You can't move or remove files from here.",
"fm_info_anonymous": "You are not logged in so your pads will expire after 3 months (<a href=\"https://blog.cryptpad.fr/2017/05/17/You-gotta-log-in/\" target=\"_blank\">find out more</a>). They are stored in your browser so clearing history may make them disappear.<br><a href=\"/register/\">Sign up</a> or <a href=\"/login/\">Log in</a> to keep them alive.<br>",
"fm_info_anonymous": "You are not logged in so your documents will expire after {0} days. Clearing your browser's history may make them disappear.<br><a href=\"/register/\">Sign up</a> (no personal information required) or <a href=\"/login/\">Log in</a> to store them in your drive indefinitely. <a href=\"https://docs.cryptpad.fr/en/user_guide/user_account.html#account-types\" target=\"_blank\">Read more about registered accounts</a>.",
"fm_info_sharedFolder": "This is a shared folder. You're not logged in so you can only access it in read-only mode.<br><a href=\"/register/\">Sign up</a> or <a href=\"/login/\">Log in</a> to be able to import it to your CryptDrive and to modify it.",
"fm_info_owned": "You are the owner of the pads displayed here. This means you can remove them permanently from the server whenever you want. If you do so, other users won't be able to access them anymore.",
"fm_alert_backupUrl": "Backup link for this drive.<br>It is <strong>highly recommended</strong> that you keep it secret.<br>You can use it to retrieve all your files in case your browser memory got erased.<br>Anybody with that link can edit or remove all the files in your file manager.<br>",
@ -1293,7 +1293,7 @@
"settings_cat_security": "Confidentiality",
"settings_safeLinksTitle": "Safe Links",
"settings_safeLinksCheckbox": "Enable safe links",
"safeLinks_error": "This link does not give you access to the document",
"safeLinks_error": "This link was copied from the browser's address bar and does not provide access to the document. Please use the <i class=\"fa fa-shhare-alt\"></i> <b>Share</b> menu to share directly with contacts or copy the link. <a href=\"https://docs.cryptpad.fr/en/user_guide/user_account.html#confidentiality\"> Read more about the Safe Links feature</a>.\n",
"dontShowAgain": "Don't show again",
"profile_login": "You need to log in to add this user to your contacts",
"settings_safeLinksHint": "CryptPad includes the keys to decrypt your pads in their links. Anyone with access to your browsing history can potentially read your data. This includes intrusive browser extensions and browsers that sync your history across devices. Enabling \"safe links\" prevents the keys from entering your browsing history or being displayed in your address bar whenever possible. We strongly recommend that you enable this feature and use the {0} Share menu.",

View File

@ -1,7 +1,7 @@
{
"wrongApp": "De sessie-inhoud kan niet in uw browser worden weergegeven. Probeer om de pagina te herladen.",
"wrongApp": "De sessie-inhoud kan niet worden getoond in uw browser. Probeer de pagina te herladen.",
"type": {
"drive": "Opslag",
"drive": "CryptDrive",
"kanban": "Kanban-bord",
"poll": "Peiling",
"pad": "Opgemaakte tekst",
@ -15,20 +15,20 @@
"slide": "Presentatie",
"code": "Code"
},
"padNotPinned": "Deze werkomgeving verloopt als deze 3 maanden niet wordt gebruikt, {0}login{1} of {2}registreer{3} om deze te behouden.",
"onLogout": "U bent uitgelogd, {0}klik hier{1} om in te loggen<br>of druk op <em>Escape</em> om uw werkomgeving in alleen-lezen modus te bekijken.",
"typeError": "Deze werkomgeving kan niet gebruikt worden met de geselecteerde applicatie",
"websocketError": "Verbinden met de websocket server is niet mogelijk...",
"common_connectionLost": "<b>Verbinding met server verbroken</b><br>Alleen-lezen modus is ingeschakeld tot de verbinding hersteld is.",
"padNotPinned": "Deze werkomgeving wordt na 3 maanden gewist als hij niet wordt gebruikt. {0}Log in{1} of {2}registreer{3} om deze te behouden.",
"onLogout": "U bent uitgelogd. {0}Klik hier{1} om in te loggen<br>of druk op <em>Escape</em> om uw werkomgeving te openen in alleen-lezenmodus.",
"typeError": "Deze werkomgeving kan niet worden gebruikt met het gekozen programma",
"websocketError": "Kan niet verbinden met de websocket-server...",
"common_connectionLost": "<b>Serververbinding verbroken</b><br>De alleen-lezenmodus is ingeschakeld tot de verbinding hersteld wordt.",
"button_newkanban": "Nieuw Kanban-bord",
"button_newwhiteboard": "Nieuw Whiteboard",
"button_newslide": "Nieuwe Presentatie",
"button_newpoll": "Nieuwe Peiling",
"button_newwhiteboard": "Nieuw whiteboard",
"button_newslide": "Nieuwe presentatie",
"button_newpoll": "Nieuwe peiling",
"button_newcode": "Nieuw codebestand",
"button_newpad": "Nieuw tekstbestand",
"button_newsheet": "Nieuw Blad",
"padNotPinnedVariable": "Deze werkomgeving zal na {4} dagen zonder gebruik verlopen, {0}login{1} of {2}registreer{3} om deze te behouden.",
"anonymousStoreDisabled": "De webmaster van deze CryptPad instantie heeft opslag uitgezet voor anonieme gebruikers. Je moet inloggen om deze CryptOpslag te gebruiken.",
"button_newpad": "Nieuw tekstbestand met opmaak",
"button_newsheet": "Nieuw blad",
"padNotPinnedVariable": "Deze werkomgeving wordt na {4} dagen gewist als hij niet wordt gebruikt. {0}Log in{1} of {2}registreer{3} om deze te behouden.",
"anonymousStoreDisabled": "De webmaster van deze CryptPad-instantie heeft opslag uitgeschakeld voor anonieme gebruikers. Log in om deze CryptOpslag te gebruiken.",
"settings_ownDriveTitle": "Account bijwerken",
"settings_creationSkipTrue": "Sla over",
"kanban_editBoard": "Bewerk dit bord",
@ -53,96 +53,96 @@
"fileEmbedTag": "Daarna plaatst u deze Media Tag op een lokatie naar keuze op de pagina om te integreren:",
"fileEmbedScript": "Om dit bestand te integreren sluit u dit script in op uw pagina om de Media Tag te laden:",
"fileEmbedTitle": "Integreer het bestand in een externe pagina",
"viewEmbedTag": "Om deze werkomgeving te integreren plaatst u dit iframe op uw pagina op een lokatie naar keuze. Maak gebruik van CSS of HTML attributen om de vormgeving aan te passsen.",
"fileShare": "Kopieer link",
"viewOpenTitle": "Open deze werkomgeving in alleen-lezen modus in een nieuw tabblad",
"viewOpen": "Open de alleen-lezen link in een nieuw tabblad",
"viewShareTitle": "Kopieer de alleen-lezen link naar het klembord",
"viewShare": "Alleen-lezen link",
"editOpenTitle": "Open deze werkomgeving in bewerkingsmodus in een nieuw tabblad",
"editOpen": "Open de link om te bewerken in een nieuw tabblad",
"editShareTitle": "Kopieer de link om te bewerken naar het klembord",
"editShare": "Link om te bewerken",
"themeButtonTitle": "Kies het kleurenschema voor de code- en diabewerker",
"viewEmbedTag": "Om deze werkomgeving te integreren, plaatst u dit iframe op uw pagina op een locatie naar keuze. Maak gebruik van css of html-attributen om de vormgeving aan te passen.",
"fileShare": "Link kopiëren",
"viewOpenTitle": "Werkomgeving openen in alleen-lezenmodus op nieuw tabblad",
"viewOpen": "Alleen-lezenlink openen op nieuw tabblad",
"viewShareTitle": "Alleen-lezenlink kopiëren naar klembord",
"viewShare": "Alleen-lezenlink",
"editOpenTitle": "Werkomgeving openen in bewerkmodus op een nieuw tabblad",
"editOpen": "Bewerklink openen op nieuw tabblad",
"editShareTitle": "Bewerklink kopiëren naar klembord",
"editShare": "Bewerklink",
"themeButtonTitle": "Kies het kleurenschema van de code- en diabewerker",
"themeButton": "Schema",
"languageButtonTitle": "Kies de taal voor syntaxisaccentuering",
"languageButton": "Taal",
"slide_invalidLess": "Ongeldige aangepaste stijl",
"slideOptionsButton": "Opslaan (enter)",
"slideOptionsTitle": "Uw dias aanpassen",
"slideOptionsTitle": "Dia's aanpassen",
"slideOptionsText": "Opties",
"tags_noentry": "U kunt een verwijderde werkomgeving niet markeren!",
"tags_duplicate": "Gedupliceerde markering: {0}",
"tags_notShared": "Uw markeringen worden niet gedeeld met andere gebruikers",
"tags_add": "Werk de markeringen van deze pagina bij",
"tags_add": "Werk de markeringen van de geselecteerde werkomgevingen bij",
"tags_title": "Markeringen (alleen voor u)",
"or": "of",
"filePicker_filter": "Filter bestanden op naam",
"filePicker_description": "Kies een bestand van uw CryptDrive om te integreren of upload een nieuw bestand",
"filePicker_filter": "Bestanden filteren op naam",
"filePicker_description": "Kies een bestand van uw CryptDrive of upload een nieuw bestand",
"filePicker_close": "Sluiten",
"filePickerButton": "Integreer een bestand opgeslagen op CryptDrive",
"printBackgroundRemove": "Verwijder deze achtergrondafbeelding",
"printBackgroundNoValue": "<em>Geen achtergrondafbeelding weergegeven</em>",
"filePickerButton": "Integreer een op CryptDrive opgeslagen bestand",
"printBackgroundRemove": "Achtergrondafbeelding verwijderen",
"printBackgroundNoValue": "<em>Geen achtergrondafbeelding</em>",
"printBackgroundValue": "<b>Huidige achtergrond:</b><em>{0}</em>",
"printBackgroundButton": "Kies een afbeelding",
"printBackground": "Gerbuik een achtergrondafbeelding",
"printTransition": "Schakel overgangsanimaties in",
"printCSS": "Aangepaste stijlregels (CSS):",
"printTitle": "Toon naam van de werkomgeving",
"printDate": "Toon datum",
"printSlideNumber": "Toon dianummer",
"printOptions": "Opmaak opties",
"printButtonTitle2": "Print uw document of exporteer het als een PDF bestand",
"printButton": "Printen (enter)",
"printText": "Printen",
"propertiesButtonTitle": "Laad werkomgeving eigenschappen",
"printBackground": "Achtergrondafbeelding gebruiken",
"printTransition": "Overgangsanimaties gebruiken",
"printCSS": "Aangepaste stijlregels (css):",
"printTitle": "Naam van werkomgeving tonen",
"printDate": "Datum tonen",
"printSlideNumber": "Dianummers tonen",
"printOptions": "Vormgevingsopties",
"printButtonTitle2": "Druk uw document af of exporteer het naar een pdf-bestand",
"printButton": "Afdrukken (enter)",
"printText": "Afdrukken",
"propertiesButtonTitle": "Laad de werkomgevingseigenschappen",
"propertiesButton": "Eigenschappen",
"colorButtonTitle": "Wijzig de tekstkleur in presentatiemodus",
"colorButtonTitle": "Wijzig de tekstkleur van de presentatie",
"backgroundButtonTitle": "Wijzig de achtergrondkleur van de presentatie",
"presentButtonTitle": "Presentatiemodus ingaan",
"previewButtonTitle": "Markdown voorbeeldmodus weergeven of verbergen",
"presentButtonTitle": "Presentatiemodus starten",
"previewButtonTitle": "Toon of verberg de Markdown-voorvertoning",
"useTemplateCancel": "Met leeg bestand beginnen (Esc)",
"saveTemplatePrompt": "Kies een titel voor het sjabloon",
"saveTemplatePrompt": "Geef het sjabloon een naam",
"template_empty": "Geen sjabloon beschikbaar",
"template_import": "Importeer een sjabloon",
"useTemplateOK": "Kies een sjabloon (Enter)",
"useTemplate": "Beginnen met een sjabloon?",
"selectTemplate": "Kies een sjabloon of druk op escape",
"templateSaved": "Sjabloon opgeslagen!",
"templateSaved": "Het sjabloon is opgeslagen!",
"saveTemplateButton": "Opslaan als sjabloon",
"uploadButtonTitle": "Upload een nieuw bestand naar de huidige map",
"uploadFolderButton": "Uploadmap",
"uploadButton": "Bestanden uploaden",
"newButtonTitle": "Maak een nieuwe werkomgeving aan",
"newButtonTitle": "Nieuwe werkomgeving aanmaken",
"newButton": "Nieuw",
"userAccountButton": "Uw account",
"userAccountButton": "Mijn account",
"chatButton": "Chat",
"userListButton": "Gebruikerslijst",
"shareSuccess": "Link gekopieerd naar het klembord",
"shareButton": "Deel",
"movedToTrash": "Die werkomgeving was verplaatst naar de prullenbak.<br><a href=\"/drive/\">Ga naar uw Drive</a>",
"forgetPrompt": "Door op OK te drukken wordt deze werkomgeving verplaatst naar de prullenbak. Weet u dit zeker?",
"forgetButtonTitle": "Verplaats deze werkomgeving naar de prullenbak",
"forgetButton": "Verwijder",
"shareSuccess": "De link is gekopieerd naar het klembord",
"shareButton": "Delen",
"movedToTrash": "De werkomgeving is verplaatst naar de prullenbak.<br><a href=\"/drive/\">Ga naar uw Drive</a>",
"forgetPrompt": "Weet u zeker dat u deze werkomgeving wilt verplaatsen naar de prullenbak?",
"forgetButtonTitle": "Werkomgeving verplaatsen naar prullenbak",
"forgetButton": "Verwijderen",
"saveTitle": "Titel opslaan (enter)",
"clickToEdit": "Klik om te bewerken",
"user_accountName": "Accountnaam",
"user_displayName": "Weergavenaam",
"user_rename": "Wijzig weergavenaam",
"changeNamePrompt": "Wijzig uw naam (leeglaten om anoniem te zijn): ",
"exportPrompt": "Hoe zou u uw bestand willen noemen?",
"user_rename": "Weergavenaam wijzigen",
"changeNamePrompt": "Wijzig uw naam (vul niks in om anoniem te blijven): ",
"exportPrompt": "Hoe wilt u uw bestand noemen?",
"exportButtonTitle": "Exporteer een werkomgeving naar een lokaal bestand",
"exportButton": "Exporteer",
"importButtonTitle": "Importeer een werkomgeving vanuit een lokaal bestand",
"importButton": "Importeer",
"exportButton": "Exporteren",
"importButtonTitle": "Importeer een werkomgeving uit een lokaal bestand",
"importButton": "Importeren",
"moreActions": "Meer acties",
"pinLimitDrive": "U heeft uw opslaglimiet bereikt.<br>U kunt geen nieuwe werkomgevingen aanmaken.",
"pinLimitNotPinned": "U heeft uw opslaglimiet bereikt.<br>Deze werkomgeving wordt niet opgeslagen op uw CryptDrive.",
"pinLimitReachedAlertNoAccounts": "U heeft uw opslaglimiet bereikt",
"pinLimitReachedAlert": "U heeft uw opslaglimiet bereikt. Nieuwe werkomgevingen worden niet opgeslagen in uw CryptDrive.<br>U kunt werkomgevingen verwijderen van uw CryptDrive of <a href=\"https://accounts.cryptpad.fr/#!on={0}\" target=\"_blank\">aanmelden voor een premium account</a> om uw opslaglimiet te verhogen.",
"pinLimitReachedAlert": "U heeft uw opslaglimiet bereikt. Nieuwe werkomgevingen worden niet opgeslagen in uw CryptDrive.<br>U kunt werkomgevingen verwijderen van uw CryptDrive of <a href=\"https://accounts.cryptpad.fr/#!on={0}\" target=\"_blank\">opwaarderen naar een premium-account</a> om uw opslaglimiet te verhogen.",
"pinLimitReached": "U heeft uw opslaglimiet bereikt",
"redLight": "U bent de verbinding kwijt met de sessie",
"orangeLight": "Uw langzame verbinding kan gevolgen hebben voor uw ervaring",
"redLight": "De verbinding met de sessie is verbroken",
"orangeLight": "Uw langzame verbinding kan van invloed zijn op de gebruikservaring",
"greenLight": "Alles werkt naar behoren",
"formattedKB": "{0} KB",
"formattedGB": "{0} GB",
@ -152,42 +152,42 @@
"GB": "GB",
"MB": "MB",
"storageStatus": "Opslag:<br /><b>{0}</b> verbruikt van <b>{1}</b>",
"upgradeAccount": "Upgrade account",
"upgradeTitle": "Upgrade uw account om meer opslag te krijgen",
"upgrade": "Upgrade",
"newVersion": "<b>CryptPad is geüpdated!</b><br>Bekijk wat veranderd is in de nieuwste versie:<br><a href=\"https://github.com/xwiki-labs/cryptpad/releases/tag/{0}\" target=\"_blank\">Release notes voor CryptPad {0}</a>",
"upgradeAccount": "Account opwaarderen",
"upgradeTitle": "Waarder uw account op om meer opslag te verkrijgen",
"upgrade": "Opwaarderen",
"newVersion": "<b>CryptPad is bijgewerkt!</b><br>Bekijk wat er veranderd is in de nieuwste versie:<br><a href=\"https://github.com/xwiki-labs/cryptpad/releases/tag/{0}\" target=\"_blank\">CryptPad-wijzigingslog {0}</a>",
"comingSoon": "Komt binnenkort...",
"language": "Taal",
"userlist_offline": "U bent nu offline, de lijst van gebruikers is niet beschikbaar.",
"userlist_offline": "U bent momenteel offline. De gebruikerslijst is niet beschikbaar.",
"editors": "bewerkers",
"editor": "bewerker",
"viewers": "kijkers",
"viewer": "kijker",
"viewers": "lezers",
"viewer": "lezer",
"and": "En",
"users": "Gebruikers",
"anonymousUser": "anonieme bewerker",
"anonymousUsers": "anonieme bewerkers",
"yourself": "Uzelf",
"yourself": "Ik",
"anonymous": "Anoniem",
"readonly": "Alleen lezen",
"readonly": "Alleen-lezen",
"lag": "Vertraging",
"errorState": "Kritieke fout: {0}",
"forgotten": "Verplaatst naar de prullenbak",
"initializing": "Initialiseren...",
"initializing": "Bezig met initialiseren...",
"typing": "Aan het bewerken",
"reconnecting": "Opnieuw aan het verbinden",
"synchronizing": "Synchroniseren",
"reconnecting": "Bezig met herverbinden",
"synchronizing": "Bezig met synchroniseren",
"disconnected": "Verbinding verbroken",
"realtime_unrecoverableError": "Een onherstelbare fout heeft plaatsgevonden. Druk op OK om de pagina te herladen.",
"disabledApp": "Deze applicatie is buiten werking gesteld. Neem contact op met de beheerder van deze CryptPad voor meer informatie.",
"mustLogin": "U moet ingelogd zijn om toegang te krijgen tot deze pagina",
"realtime_unrecoverableError": "Er is een onherstelbare fout opgetreden. Klik op 'Oké' om de pagina te herladen.",
"disabledApp": "Deze applicatie is buiten werking gesteld. Neem contact op met de beheerder van deze CryptPad-instantie.",
"mustLogin": "Log in om toegang te krijgen tot deze pagina",
"deletedFromServer": "Werkomgeving verwijderd van de server",
"deleted": "Verwijderd",
"synced": "Alles is opgeslagen",
"saved": "Opgeslagen",
"error": "Fout",
"loading": "Laden...",
"newVersionError": "Een nieuwe versie van CryptPad is beschikbaar.<br><a href='#'>Herlaad de pagina</a> om de nieuwe versie te gebruiken, of druk escape om uw inhoud te bekijken in <b>offline modus</b>.",
"loading": "Bezig met laden...",
"newVersionError": "Er is een nieuwe versie van CryptPad beschikbaar.<br><a href='#'>Herlaad de pagina</a> om de nieuwe versie te gebruiken of druk Esc om uw inhoud te bekijken in de <b>offline-modus</b>.",
"oo_isLocked": "synchroniseert wijzigingen, gelieve te wachten",
"settings_changePasswordTitle": "Wijzig uw wachtwoord",
"settings_ownDrivePending": "Uw account wordt geüpgraded. Gelieve deze pagina niet te sluiten of te herladen totdat dit voltooid is.",
@ -195,12 +195,12 @@
"settings_ownDriveButton": "Upgrade uw account",
"settings_ownDriveHint": "Oude accounts hebben geen toegang tot de nieuwste functies. Een gratis update zal nieuwe functies inschakelen en jouw Drive voor toekomstige updates voorbereiden.",
"errorRedirectToHome": "Druk op <em>Esc</em> om door te gaan naar uw CryptDrive.",
"errorCopy": " U kunt nog steeds toegang krijgen tot de inhoud als u op <em>Esc</em> drukt.<br>Als u dit venster sluit kunt u er geen toegang meer tot krijgen.",
"invalidHashError": "Het document dat u opvroeg heeft een ongeldige URL.",
"chainpadError": "Er was een kritieke fout bij het updaten van uw inhoud. Deze pagina is nu alleen leesbaar om uw werk niet kwijt te raken. <br>Druk op <em>Esc</em> om verder te gaan met het bekijken van deze werkomgeving, of herlaad de pagina om te proberen deze werkomgeving weer aan te kunnen passen.",
"inactiveError": "Deze werkomgeving is verwijderd wegens gebrek aan activiteit. Druk op Esc om een nieuwe werkomgeving aan te maken.",
"deletedError": "Deze werkomgeving is verwijderd door de eigenaar en is niet meer beschikbaar.",
"main_title": "CryptPad: Geen Kennis, Onvertraagd Collaboratief Aanpassen",
"errorCopy": " U kunt nog altijd toegang krijgen tot de inhoud als u op <em>Esc</em> drukt.<br>Als u dit venster sluit, kunt u er geen toegang meer tot krijgen.",
"invalidHashError": "De url van het opgevraagde document is ongeldig.",
"chainpadError": "Er is een kritieke fout opgetreden tijdens het bijwerken van uw inhoud. Deze pagina bevindt zich nu in alleen-lezenmodus zodat u uw werk niet kwijtraakt. <br>Druk op <em>Esc</em> om door te gaan met het bekijken van deze werkomgeving of herlaad de pagina om te trachten deze werkomgeving weer aan te kunnen passen.",
"inactiveError": "Deze werkomgeving is verwijderd wegens gebrek aan activiteit. Druk op Esc om een nieuwe werkomgeving samen te stellen.",
"deletedError": "Deze werkomgeving is verwijderd door de eigenaar en niet meer beschikbaar.",
"main_title": "CryptPad: werk samen aan documenten - geen kennis benodigd",
"fc_open_ro": "Openen (alleen-lezen)",
"history_restorePrompt": "Weet u zeker dat u de bestaande documentversie wilt vervangen met de weergegeven versie?",
"history_restoreDone": "Document hersteld",
@ -371,7 +371,7 @@
"fc_empty": "Prullenbak legen",
"fc_prop": "Eigenschappen",
"fc_hashtag": "Markeringen",
"getEmbedCode": "Krijg integratiecode",
"getEmbedCode": "Insluitcode ophalen",
"kanban_done": "Gedaan",
"poll_comment_remove": "Verwijder dit commentaar",
"profile_fieldSaved": "Nieuwe waarde opgeslagen: {0}",

View File

@ -373,14 +373,14 @@
"fm_burnThisDriveButton": "Удалить всю информацию, хранящуюся от CryptPad в браузере",
"fm_tags_used": "Количество использований",
"fm_restoreDrive": "Восстановление прежнего состояния диска. Для достижения наилучших результатов не вносите изменения в диск, пока этот процесс не будет завершен.",
"fm_passwordProtected": "Этот документ защищен паролем",
"fm_passwordProtected": "Защищено паролем",
"fc_newfolder": "Новая папка",
"fc_newsharedfolder": "Новая общая папка",
"fc_rename": "Переименовать",
"fc_open": "Открыть",
"fc_open_ro": "Отркыть (режим чтения)",
"fc_delete": "Переместить в корзину",
"fc_delete_owned": "Удалить с сервера",
"fc_delete_owned": "Уничтожить",
"fc_restore": "Восстановить",
"fc_remove_sharedfolder": "Удалить",
"fc_empty": "Удалить корзину",
@ -392,7 +392,7 @@
"fc_color": "Изменить цвет",
"fc_expandAll": "Расширить все",
"fc_collapseAll": "Скрыть все",
"fc_remove": "Удалить из вашего CryptDrive",
"fc_remove": "Удалить",
"fo_moveUnsortedError": "Вы не можете переместить папку в список черновиков",
"fo_existingNameError": "Это имя уже используется в данной директории. Пожалуйста выберите другое.",
"fo_unableToRestore": "Невозможно восстановить этот файл в исходное местоположение. Вы можете попытаться переместить его в другое место.",
@ -540,5 +540,99 @@
"fm_morePads": "Ещё",
"uploadFolderButton": "Загрузить папку",
"storageStatus": "Хранилище:<br /><b>{0}</b> использовано из <b>{1}</b>",
"padNotPinnedVariable": "Этот документ исчезнет через {4} дней неактивности, {0}войдите{1} или {2}зарегистируйтесь{3} чтобы сохранить его."
"padNotPinnedVariable": "Этот документ исчезнет через {4} дней неактивности, {0}войдите{1} или {2}зарегистируйтесь{3} чтобы сохранить его.",
"creation_propertiesTitle": "Доступность",
"creation_passwordValue": "Пароль",
"creation_owners": "Владельцы",
"creation_create": "Создать",
"creation_expireMonths": "Месяцев",
"creation_expireDays": "Дней",
"creation_expireHours": "Часов",
"creation_expireFalse": "Неограниченно",
"view": "показать",
"edit": "редактировать",
"faq": {
"usability": {
"title": "Удобство использования"
},
"security": {
"title": "Безопасность"
},
"privacy": {
"title": "Конфиденциальность"
}
},
"settings_ownDriveTitle": "Обновить аккаунт",
"settings_templateSkipHint": "При создании нового документа, если для этого типа документов были сохранены шаблоны, вам будет предложено их использовать. Вы можете выбрать никогда не показывать окно с этим предложением, а значит никогда не использовать шаблоны.",
"settings_templateSkip": "Пропускать экран выбора шаблонов",
"settings_creationSkipFalse": "Отображать",
"settings_creationSkipHint": "Экран создания документов предлагает новые опции, давая вам больше контроля над вашими данными. Однако, он может замедлить вашу работу, добавив дополнительный шаг, так что вы можете пропустить этот экран, согласившись на выбранные выше настройки по умолчанию.",
"settings_padSpellcheckLabel": "Включить проверку написания",
"settings_padSpellcheckHint": "Эта опция включает проверку написания. Ошибки будут подчёркнуты красным, нажмите на них правой кнопкой мыши, удерживая клавишу Ctrl или Meta для просмотра исправленных вариантов.",
"settings_padWidthHint": "Переключайтесь между режимом страницы (по умолчанию) с ограниченной шириной редактора и использованием полной ширины экрана.",
"settings_codeIndentation": "Отступы редактора кода (пробелы)",
"settings_driveDuplicateHint": "Когда вы помещаете присвоенные документы в общую папку, копия сохраняется в вашем хранилище, чтобы удостовериться, что вы все еще имеете над ними контроль. Вы можете скрыть продублированные файлы. Будет отображена только общая версия документа, если она не удалена, в этом случае будет отображена оригинальная версия в своей последней локации.",
"settings_driveDuplicateTitle": "Продублированы присвоенные документы",
"settings_logoutEverywhereConfirm": "Вы уверены? Вам придётся войти в аккаунт на всех устройствах.",
"settings_autostoreHint": "<b>Автоматически</b> Все открытые вами документы будут сохранены в вашем хранилище.<br><b>Вручную (всегда спрашивать)</b> Если вы еще не сохраняли документов, вам будет предложено сохранить документ в хранилище.<br><b>Вручную (никогда не спрашивать)</b> Документы не будут сохраняться в вашем хранилище. Кнопка для их сохранения будет скрыта.",
"register_emailWarning3": "Нажмите OK, если осознанно хотите использовать свою почту в качестве имени пользователя.",
"register_emailWarning2": "Восстановить ваш пароль с помощью почты, как на других сайтах, не получится.",
"register_emailWarning1": "Вы можете сделать это, если хочется, но на наш сервер это отправлено не будет.",
"register_emailWarning0": "Похоже, что ваша почта и имя пользователя совпадают.",
"register_explanation": "<h3>Проясним несколько вещей:</h3><ul class='list-unstyled'><li><i class='fa fa-info-circle'> </i>Ваш пароль - это ваш секретный ключ, шифрующий всеваши документы. Если вы его забудете, восстановить ваши данные будет невозможно.</li><li><i class='fa fa-info-circle'> </i> Вы можете импортировать недавно просмотренные в браузере документы в ваш аккаунт.</li><li><i class='fa fa-info-circle'> </i> Если вы пользуетесь общим компьютером: по завершении работы необходимо выйти из системы, закрытия вкладки в браузере недостаточно.</li></ul>",
"password_submit": "Отправить",
"team_pendingOwner": "(ожидание)",
"team_deleteButton": "Удалить",
"team_pending": "Приглашённые",
"team_members": "Участники",
"team_admins": "Администраторы",
"team_owner": "Владельцы",
"team_rosterDemote": "Понизить",
"team_rosterPromote": "Повысить",
"team_listLoad": "Открыть",
"team_cat_admin": "Администрация",
"team_cat_drive": "Хранилище",
"team_cat_chat": "Чат",
"team_cat_members": "Участники",
"team_cat_create": "Создать",
"team_cat_list": "Команды",
"team_cat_general": "Сведения",
"team_inviteModalButton": "Пригласить",
"owner_unknownUser": "неизвестный",
"owner_removePendingText": "Ожидает",
"owner_removeText": "Владельцы",
"pricing": "Цены",
"notifications_cat_archived": "История",
"notifications_cat_all": "Все",
"notificationsPage": "Уведомления",
"support_answer": "Ответить",
"support_formButton": "Отправить",
"admin_cat_support": "Поддержка",
"supportPage": "Поддержка",
"notifications_dismiss": "Скрыть",
"share_withFriends": "Поделиться",
"friendRequest_decline": "Отклонить",
"settings_codeSpellcheckTitle": "Проверка правописания",
"contact_email": "Эл. почта",
"contact_chat": "Чат",
"footer_tos": "Условия использования",
"footer_legal": "Юридическая информация",
"footer_donate": "Пожертвовать",
"footer_product": "Продукт",
"adminPage": "Администрация",
"admin_cat_stats": "Статистика",
"admin_cat_general": "Общее",
"autostore_store": "Хранить",
"autostore_pad": "документ",
"autostore_sf": "папка",
"autostore_file": "файл",
"share_embedCategory": "Вставить",
"share_linkCopy": "Копировать",
"share_linkOpen": "Предпросмотр",
"share_linkPresent": "Текущий",
"share_linkView": "Посмотреть",
"share_linkEdit": "Изменить",
"share_linkCategory": "Ссылка",
"properties_changePasswordButton": "Отправить",
"password_show": "Показать"
}

View File

@ -9,7 +9,11 @@
"whiteboard": "白板",
"file": "檔案",
"media": "多媒體",
"kanban": "任务看板"
"kanban": "任务看板",
"todo": "待办事项",
"teams": "团队",
"sheet": "工作表",
"contacts": "联系我们"
},
"button_newpad": "富文件檔案",
"button_newcode": "新代碼檔案",
@ -25,7 +29,7 @@
"error": "錯誤",
"saved": "儲存",
"synced": "所有資料已儲存好了",
"deleted": "自 CryptDrive 刪除案",
"deleted": "自 CryptDrive 刪除案",
"disconnected": "已斷線",
"synchronizing": "同步中",
"reconnecting": "重新連結...",
@ -335,5 +339,32 @@
},
"feedback_about": "如果你讀了這裏,也許會好奇為何當你執行某些動作時 CryptPad 會請求網頁資訊。",
"feedback_privacy": "我們注重你的隱私,同時也要讓 CryptPad 容易使用。我們利用這個檔案來了解哪一種介面設計為用戶所重視,透過它來請求特別的功能參數。",
"feedback_optout": "如果欲退出客戶資料收集, 請到 <a href='/settings/'>用戶設定頁</a>, 可以找到勾選項目來啟用或關閉用戶回饋功能。"
"feedback_optout": "如果欲退出客戶資料收集, 請到 <a href='/settings/'>用戶設定頁</a>, 可以找到勾選項目來啟用或關閉用戶回饋功能。",
"settings_cat_kanban": "看板",
"themeButton": "主题",
"languageButton": "语言",
"slideOptionsText": "选项",
"or": "或者",
"filePicker_close": "关闭",
"printText": "打印",
"propertiesButton": "属性",
"chatButton": "聊天",
"forgetButton": "删除",
"exportButton": "导出",
"importButton": "导入",
"forgotten": "移到垃圾箱",
"initializing": "初始化中",
"typing": "编辑中",
"profile_editDescription": "编辑描述",
"profile_addDescription": "添加描述",
"poll_comment_submit": "发送",
"poll_comment_list": "评论",
"poll_edit": "编辑",
"poll_remove": "删除",
"kanban_done": "完成",
"pad_mediatagPreview": "预览",
"historyText": "历史",
"help_button": "帮助",
"button_newsheet": "新工作表",
"button_newkanban": "新看板"
}

View File

@ -6,6 +6,7 @@ define([
'/bower_components/nthen/index.js',
'/common/sframe-common.js',
'/common/common-util.js',
'/common/common-hash.js',
'/common/common-interface.js',
'/common/common-ui-elements.js',
'/common/common-realtime.js',
@ -33,6 +34,7 @@ define([
nThen,
SFCommon,
Util,
Hash,
UI,
UIElements,
Realtime,
@ -481,9 +483,7 @@ define([
APP.getEdPublic = function () {
var metadataMgr = APP.common.getMetadataMgr();
var privateData = metadataMgr.getPrivateData();
var name = data.name.toLowerCase().replace(/[^a-zA-Z0-9]+/g, "-");
var ed = data.edPublic.replace(/\//g, '-');
var url = privateData.origin + '/user/#/1/' + name + '/' + ed;
var url = Hash.getPublicSigningKeyString(privateData.origin, data.name, data.edPublic);
var success = Clipboard.copy(url);
if (success) { UI.log(Messages.shareSuccess); }
};

View File

@ -45,32 +45,33 @@ define([
// Share modal
create['share'] = function (data) {
var priv = metadataMgr.getPrivateData();
var f = (data && data.file) ? UIElements.createFileShareModal
: UIElements.createShareModal;
var friends = common.getFriends();
var _modal;
var modal = f({
origin: priv.origin,
pathname: priv.pathname,
password: priv.password,
isTemplate: priv.isTemplate,
hashes: priv.hashes,
common: common,
title: data.title,
friends: friends,
onClose: function () {
if (_modal && _modal.close) { _modal.close(); }
hideIframe();
},
fileData: {
hash: priv.hashes.fileHash,
password: priv.password
}
require(['/common/inner/share.js'], function (Share) {
var f = (data && data.file) ? Share.getFileShareModal
: Share.getShareModal;
f(common, {
origin: priv.origin,
pathname: priv.pathname,
password: priv.password,
isTemplate: priv.isTemplate,
hashes: priv.hashes,
common: common,
title: data.title,
versionHash: data.versionHash,
friends: friends,
onClose: function () {
hideIframe();
},
fileData: {
hash: priv.hashes.fileHash,
password: priv.password
}
}, function (e, modal) {
if (e) { console.error(e); }
displayed = modal;
});
});
_modal = UI.openCustomModal(modal);
displayed = modal;
};
// Properties modal