From 26aeb7b7054a2e7b24aa691a7d47e57ad5e08fdc Mon Sep 17 00:00:00 2001 From: Brian Lim Date: Thu, 21 Jan 2016 07:38:41 -0500 Subject: [PATCH 001/102] Added pad shortcut disabling feature --- settings.json.template | 24 +++++++++ src/node/hooks/express/specialpages.js | 6 +++ src/node/utils/Settings.js | 28 +++++++++- src/static/js/ace2_inner.js | 74 ++++++++++++++++++-------- 4 files changed, 110 insertions(+), 22 deletions(-) diff --git a/settings.json.template b/settings.json.template index ceb9efb31..404ce1c78 100644 --- a/settings.json.template +++ b/settings.json.template @@ -69,6 +69,30 @@ "lang": "en-gb" }, + /* Pad Shortcut Keys */ + "padShortcutEnabled" : { + "altF9" : true, + "altC" : true, + "cmdShift2" : true, + "delete" : true, + "return" : true, + "cmdS" : true, + "tab" : true, + "cmdZ" : true, + "cmdY" : true, + "cmdI" : true, + "cmdB" : true, + "cmdU" : true, + "cmd5" : true, + "cmdShiftL" : true, + "cmdShiftN" : true, + "cmdShiftC" : true, + "cmdH" : true, + "ctrlHome" : true, + "pageUp" : true, + "pageDown" : true, + }, + /* Should we suppress errors from being visible in the default Pad Text? */ "suppressErrorsInPadText" : false, diff --git a/src/node/hooks/express/specialpages.js b/src/node/hooks/express/specialpages.js index e8d7795a6..b9f86367c 100644 --- a/src/node/hooks/express/specialpages.js +++ b/src/node/hooks/express/specialpages.js @@ -41,6 +41,12 @@ exports.expressCreateServer = function (hook_name, args, cb) { res.cookie('language', settings.padOptions.lang); } + // Enable the pad shortcut keys from settings.json + if (settings.padShortcutEnabled !== undefined) + { + res.cookie('padShortcutEnabled', JSON.stringify(settings.padShortcutEnabled)); + } + // The below might break for pads being rewritten var isReadOnly = req.url.indexOf("/p/r.") === 0; diff --git a/src/node/utils/Settings.js b/src/node/utils/Settings.js index b765670a6..9f31e5579 100644 --- a/src/node/utils/Settings.js +++ b/src/node/utils/Settings.js @@ -100,7 +100,33 @@ exports.padOptions = { "alwaysShowChat": false, "chatAndUsers": false, "lang": "en-gb" -} +}, + +/** + * Whether certain shortcut keys are enabled for a user in the pad + */ +exports.padShortcutEnabled = { + "altF9" : true, + "altC" : true, + "delete" : true, + "cmdShift2" : true, + "return" : true, + "cmdS" : true, + "tab" : true, + "cmdZ" : true, + "cmdY" : true, + "cmdB" : true, + "cmdI" : true, + "cmdU" : true, + "cmd5" : true, + "cmdShiftL" : true, + "cmdShiftN" : true, + "cmdShiftC" : true, + "cmdH" : true, + "ctrlHome" : true, + "pageUp" : true, + "pageDown" : true, +}, /** * The toolbar buttons and order. diff --git a/src/static/js/ace2_inner.js b/src/static/js/ace2_inner.js index 8576ee336..88abbf865 100644 --- a/src/static/js/ace2_inner.js +++ b/src/static/js/ace2_inner.js @@ -61,6 +61,7 @@ function Ace2Inner(){ var SkipList = require('./skiplist'); var undoModule = require('./undomodule').undoModule; var AttributeManager = require('./AttributeManager'); + var readCookie = require('./pad_utils').readCookie; var DEBUG = false; //$$ build script replaces the string "var DEBUG=true;//$$" with "var DEBUG=false;" // changed to false @@ -3633,6 +3634,37 @@ function Ace2Inner(){ function handleKeyEvent(evt) { + // Get the enabled shortcut keys + // If it can't find the cookie, use default values + // Cookie should normally be set + // See settings.json + var padShortcutEnabled = JSON.parse(decodeURIComponent(readCookie('padShortcutEnabled'))); + if (!padShortcutEnabled) + { + padShortcutEnabled = { + "altF9" : true, + "altC" : true, + "cmdShift2" : true, + "delete" : true, + "return" : true, + "cmdS" : true, + "tab" : true, + "cmdZ" : true, + "cmdY" : true, + "cmdI" : true, + "cmdB" : true, + "cmdU" : true, + "cmd5" : true, + "cmdShiftL" : true, + "cmdShiftN" : true, + "cmdShiftC" : true, + "cmdH" : true, + "ctrlHome" : true, + "pageUp" : true, + "pageDown" : true, + } + } + // if (DEBUG && window.DONT_INCORP) return; if (!isEditable) return; var type = evt.type; @@ -3716,7 +3748,7 @@ function Ace2Inner(){ specialHandled = _.contains(specialHandledInHook, true); } - if ((!specialHandled) && altKey && isTypeForSpecialKey && keyCode == 120){ + if ((!specialHandled) && altKey && isTypeForSpecialKey && keyCode == 120 && padShortcutEnabled.altF9){ // Alt F9 focuses on the File Menu and/or editbar. // Note that while most editors use Alt F10 this is not desirable // As ubuntu cannot use Alt F10.... @@ -3726,14 +3758,14 @@ function Ace2Inner(){ firstEditbarElement.focus(); evt.preventDefault(); } - if ((!specialHandled) && altKey && keyCode == 67 && type === "keydown"){ + if ((!specialHandled) && altKey && keyCode == 67 && type === "keydown" && padShortcutEnabled.altC){ // Alt c focuses on the Chat window $(this).blur(); parent.parent.chat.show(); parent.parent.$("#chatinput").focus(); evt.preventDefault(); } - if ((!specialHandled) && evt.ctrlKey && shiftKey && keyCode == 50 && type === "keydown"){ + if ((!specialHandled) && evt.ctrlKey && shiftKey && keyCode == 50 && type === "keydown" && padShortcutEnabled.cmdShift2){ // Control-Shift-2 shows a gritter popup showing a line author var lineNumber = rep.selEnd[0]; var alineAttrs = rep.alines[lineNumber]; @@ -3811,7 +3843,7 @@ function Ace2Inner(){ time: '4000' }); } - if ((!specialHandled) && isTypeForSpecialKey && keyCode == 8) + if ((!specialHandled) && isTypeForSpecialKey && keyCode == 8 && padShortcutEnabled.delete) { // "delete" key; in mozilla, if we're at the beginning of a line, normalize now, // or else deleting a blank line can take two delete presses. @@ -3825,7 +3857,7 @@ function Ace2Inner(){ doDeleteKey(evt); specialHandled = true; } - if ((!specialHandled) && isTypeForSpecialKey && keyCode == 13) + if ((!specialHandled) && isTypeForSpecialKey && keyCode == 13 && padShortcutEnabled.return) { // return key, handle specially; // note that in mozilla we need to do an incorporation for proper return behavior anyway. @@ -3839,7 +3871,7 @@ function Ace2Inner(){ }, 0); specialHandled = true; } - if ((!specialHandled) && isTypeForSpecialKey && keyCode == 27) + if ((!specialHandled) && isTypeForSpecialKey && keyCode == 27 && padShortcutEnabled.cmdS) { // prevent esc key; // in mozilla versions 14-19 avoid reconnecting pad. @@ -3848,7 +3880,7 @@ function Ace2Inner(){ evt.preventDefault(); specialHandled = true; } - if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "s" && (evt.metaKey || evt.ctrlKey) && !evt.altKey) /* Do a saved revision on ctrl S */ + if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "s" && (evt.metaKey || evt.ctrlKey) && !evt.altKey && padShortcutEnabled.cmdS) /* Do a saved revision on ctrl S */ { evt.preventDefault(); var originalBackground = parent.parent.$('#revisionlink').css("background") @@ -3859,7 +3891,7 @@ function Ace2Inner(){ parent.parent.pad.collabClient.sendMessage({"type":"SAVE_REVISION"}); /* The parent.parent part of this is BAD and I feel bad.. It may break something */ specialHandled = true; } - if ((!specialHandled) && isTypeForSpecialKey && keyCode == 9 && !(evt.metaKey || evt.ctrlKey)) + if ((!specialHandled) && isTypeForSpecialKey && keyCode == 9 && !(evt.metaKey || evt.ctrlKey) && padShortcutEnabled.tab) { // tab fastIncorp(5); @@ -3868,7 +3900,7 @@ function Ace2Inner(){ //scrollSelectionIntoView(); specialHandled = true; } - if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "z" && (evt.metaKey || evt.ctrlKey) && !evt.altKey) + if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "z" && (evt.metaKey || evt.ctrlKey) && !evt.altKey && padShortcutEnabled.cmdZ) { // cmd-Z (undo) fastIncorp(6); @@ -3883,7 +3915,7 @@ function Ace2Inner(){ } specialHandled = true; } - if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "y" && (evt.metaKey || evt.ctrlKey)) + if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "y" && (evt.metaKey || evt.ctrlKey) && padShortcutEnabled.cmdY) { // cmd-Y (redo) fastIncorp(10); @@ -3891,7 +3923,7 @@ function Ace2Inner(){ doUndoRedo("redo"); specialHandled = true; } - if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "b" && (evt.metaKey || evt.ctrlKey)) + if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "b" && (evt.metaKey || evt.ctrlKey) && padShortcutEnabled.cmdB) { // cmd-B (bold) fastIncorp(13); @@ -3899,7 +3931,7 @@ function Ace2Inner(){ toggleAttributeOnSelection('bold'); specialHandled = true; } - if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "i" && (evt.metaKey || evt.ctrlKey)) + if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "i" && (evt.metaKey || evt.ctrlKey) && padShortcutEnabled.cmdI) { // cmd-I (italic) fastIncorp(14); @@ -3907,7 +3939,7 @@ function Ace2Inner(){ toggleAttributeOnSelection('italic'); specialHandled = true; } - if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "u" && (evt.metaKey || evt.ctrlKey)) + if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "u" && (evt.metaKey || evt.ctrlKey) && padShortcutEnabled.cmdU) { // cmd-U (underline) fastIncorp(15); @@ -3915,7 +3947,7 @@ function Ace2Inner(){ toggleAttributeOnSelection('underline'); specialHandled = true; } - if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "5" && (evt.metaKey || evt.ctrlKey) && evt.altKey !== true) + if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "5" && (evt.metaKey || evt.ctrlKey) && evt.altKey !== true && padShortcutEnabled.cmd5) { // cmd-5 (strikethrough) fastIncorp(13); @@ -3923,7 +3955,7 @@ function Ace2Inner(){ toggleAttributeOnSelection('strikethrough'); specialHandled = true; } - if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "l" && (evt.metaKey || evt.ctrlKey) && evt.shiftKey) + if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "l" && (evt.metaKey || evt.ctrlKey) && evt.shiftKey && padShortcutEnabled.cmdShiftL) { // cmd-shift-L (unorderedlist) fastIncorp(9); @@ -3931,7 +3963,7 @@ function Ace2Inner(){ doInsertUnorderedList() specialHandled = true; } - if ((!specialHandled) && isTypeForCmdKey && (String.fromCharCode(which).toLowerCase() == "n" || String.fromCharCode(which) == 1) && (evt.metaKey || evt.ctrlKey) && evt.shiftKey) + if ((!specialHandled) && isTypeForCmdKey && (String.fromCharCode(which).toLowerCase() == "n" || String.fromCharCode(which) == 1) && (evt.metaKey || evt.ctrlKey) && evt.shiftKey && padShortcutEnabled.cmdShiftN) { // cmd-shift-N (orderedlist) fastIncorp(9); @@ -3939,13 +3971,13 @@ function Ace2Inner(){ doInsertOrderedList() specialHandled = true; } - if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "c" && (evt.metaKey || evt.ctrlKey) && evt.shiftKey) { + if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "c" && (evt.metaKey || evt.ctrlKey) && evt.shiftKey && padShortcutEnabled.cmdShiftC) { // cmd-shift-C (clearauthorship) fastIncorp(9); evt.preventDefault(); CMDS.clearauthorship(); } - if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "h" && (evt.ctrlKey)) + if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "h" && (evt.ctrlKey) && padShortcutEnabled.cmdH) { // cmd-H (backspace) fastIncorp(20); @@ -3953,7 +3985,7 @@ function Ace2Inner(){ doDeleteKey(); specialHandled = true; } - if((evt.which == 36 && evt.ctrlKey == true)){ setScrollY(0); } // Control Home send to Y = 0 + if((evt.which == 36 && evt.ctrlKey == true) && padShortcutEnabled.ctrlHome){ setScrollY(0); } // Control Home send to Y = 0 if((evt.which == 33 || evt.which == 34) && type == 'keydown' && !evt.ctrlKey){ evt.preventDefault(); // This is required, browsers will try to do normal default behavior on page up / down and the default behavior SUCKS @@ -3972,12 +4004,12 @@ function Ace2Inner(){ var linesCount = rep.lines.length(); // total count of lines in pad IE 10 var numberOfLinesInViewport = newVisibleLineRange[1] - newVisibleLineRange[0]; // How many lines are in the viewport right now? - if(isPageUp){ + if(isPageUp && padShortcutEnabled.pageUp){ rep.selEnd[0] = rep.selEnd[0] - numberOfLinesInViewport; // move to the bottom line +1 in the viewport (essentially skipping over a page) rep.selStart[0] = rep.selStart[0] - numberOfLinesInViewport; // move to the bottom line +1 in the viewport (essentially skipping over a page) } - if(isPageDown){ // if we hit page down + if(isPageDown && padShortcutEnabled.pageDown){ // if we hit page down if(rep.selEnd[0] >= oldVisibleLineRange[0]){ // If the new viewpoint position is actually further than where we are right now rep.selStart[0] = oldVisibleLineRange[1] -1; // dont go further in the page down than what's visible IE go from 0 to 50 if 50 is visible on screen but dont go below that else we miss content rep.selEnd[0] = oldVisibleLineRange[1] -1; // dont go further in the page down than what's visible IE go from 0 to 50 if 50 is visible on screen but dont go below that else we miss content From cd7f01f40a0b81fb373c08066381bc839c77bbcd Mon Sep 17 00:00:00 2001 From: Alexander Lorz Date: Mon, 26 Dec 2016 20:18:34 +0100 Subject: [PATCH 002/102] minor changes in docs - correct link to doc generation tool. - fixed incomplete sentence regarding API client libraries --- doc/api/http_api.md | 34 +++++++++++++++++----------------- doc/documentation.md | 4 ++-- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/doc/api/http_api.md b/doc/api/http_api.md index 93a9b3992..4b6ea50e8 100644 --- a/doc/api/http_api.md +++ b/doc/api/http_api.md @@ -3,42 +3,42 @@ ## What can I do with this API? The API gives another web application control of the pads. The basic functions are -* create/delete pads +* create/delete pads * grant/forbid access to pads * get/set pad content The API is designed in a way, so you can reuse your existing user system with their permissions, and map it to Etherpad. Means: Your web application still has to do authentication, but you can tell Etherpad via the api, which visitors should get which permissions. This allows Etherpad to fit into any web application and extend it with real-time functionality. You can embed the pads via an iframe into your website. -Take a look at [HTTP API client libraries](https://github.com/ether/etherpad-lite/wiki/HTTP-API-client-libraries) to see if a library in your favorite language. +Take a look at [HTTP API client libraries](https://github.com/ether/etherpad-lite/wiki/HTTP-API-client-libraries) to check if a library in your favorite programming language is available. ## Examples ### Example 1 -A portal (such as WordPress) wants to give a user access to a new pad. Let's assume the user have the internal id 7 and his name is michael. +A portal (such as WordPress) wants to give a user access to a new pad. Let's assume the user have the internal id 7 and his name is michael. -Portal maps the internal userid to an etherpad author. +Portal maps the internal userid to an etherpad author. > Request: `http://pad.domain/api/1/createAuthorIfNotExistsFor?apikey=secret&name=Michael&authorMapper=7` -> +> > Response: `{code: 0, message:"ok", data: {authorID: "a.s8oes9dhwrvt0zif"}}` Portal maps the internal userid to an etherpad group: > Request: `http://pad.domain/api/1/createGroupIfNotExistsFor?apikey=secret&groupMapper=7` -> +> > Response: `{code: 0, message:"ok", data: {groupID: "g.s8oes9dhwrvt0zif"}}` Portal creates a pad in the userGroup > Request: `http://pad.domain/api/1/createGroupPad?apikey=secret&groupID=g.s8oes9dhwrvt0zif&padName=samplePad&text=This is the first sentence in the pad` -> +> > Response: `{code: 0, message:"ok", data: null}` Portal starts the session for the user on the group: > Request: `http://pad.domain/api/1/createSession?apikey=secret&groupID=g.s8oes9dhwrvt0zif&authorID=a.s8oes9dhwrvt0zif&validUntil=1312201246` -> +> > Response: `{"data":{"sessionID": "s.s8oes9dhwrvt0zif"}}` Portal places the cookie "sessionID" with the given value on the client and creates an iframe including the pad. @@ -50,7 +50,7 @@ A portal (such as WordPress) wants to transform the contents of a pad that multi Portal retrieves the contents of the pad for entry into the db as a blog post: > Request: `http://pad.domain/api/1/getText?apikey=secret&padID=g.s8oes9dhwrvt0zif$123` -> +> > Response: `{code: 0, message:"ok", data: {text:"Welcome Text"}}` Portal submits content into new blog post @@ -103,7 +103,7 @@ Responses are valid JSON in the following format: ### Authentication -Authentication works via a token that is sent with each request as a post parameter. There is a single token per Etherpad deployment. This token will be random string, generated by Etherpad at the first start. It will be saved in APIKEY.txt in the root folder of Etherpad. Only Etherpad and the requesting application knows this key. Token management will not be exposed through this API. +Authentication works via a token that is sent with each request as a post parameter. There is a single token per Etherpad deployment. This token will be random string, generated by Etherpad at the first start. It will be saved in APIKEY.txt in the root folder of Etherpad. Only Etherpad and the requesting application knows this key. Token management will not be exposed through this API. ### Node Interoperability @@ -123,7 +123,7 @@ Pads can belong to a group. The padID of grouppads is starting with a groupID li #### createGroup() * API >= 1 - + creates a new group *Example returns:* @@ -132,7 +132,7 @@ creates a new group #### createGroupIfNotExistsFor(groupMapper) * API >= 1 -this functions helps you to map your application group ids to Etherpad group ids +this functions helps you to map your application group ids to Etherpad group ids *Example returns:* * `{code: 0, message:"ok", data: {groupID: g.s8oes9dhwrvt0zif}}` @@ -175,7 +175,7 @@ lists all existing groups * `{code: 0, message:"ok", data: {groupIDs: []}}` ### Author -These authors are bound to the attributes the users choose (color and name). +These authors are bound to the attributes the users choose (color and name). #### createAuthor([name]) * API >= 1 @@ -188,7 +188,7 @@ creates a new author #### createAuthorIfNotExistsFor(authorMapper [, name]) * API >= 1 -this functions helps you to map your application author ids to Etherpad author ids +this functions helps you to map your application author ids to Etherpad author ids *Example returns:* * `{code: 0, message:"ok", data: {authorID: "a.s8oes9dhwrvt0zif"}}` @@ -411,7 +411,7 @@ creates a chat message, saves it to the database and sends it to all connected c * `{code: 1, message:"text is no string", data: null}` ### Pad -Group pads are normal pads, but with the name schema GROUPID$PADNAME. A security manager controls access of them and its forbidden for normal pads to include a $ in the name. +Group pads are normal pads, but with the name schema GROUPID$PADNAME. A security manager controls access of them and its forbidden for normal pads to include a $ in the name. #### createPad(padID [, text]) * API >= 1 @@ -575,7 +575,7 @@ returns the timestamp of the last revision of the pad *Example returns:* * `{code: 0, message:"ok", data: {lastEdited: 1340815946602}}` * `{code: 1, message:"padID does not exist", data: null}` - + #### sendClientsMessage(padID, msg) * API >= 1.1 @@ -598,7 +598,7 @@ returns ok when the current api token is valid #### listAllPads() * API >= 1.2.1 - + lists all pads on this epl instance *Example returns:* diff --git a/doc/documentation.md b/doc/documentation.md index 2452ec084..ba4dc61f0 100644 --- a/doc/documentation.md +++ b/doc/documentation.md @@ -11,5 +11,5 @@ heading. Every `.html` file is generated based on the corresponding `.markdown` file in the `doc/api/` folder in the source tree. The -documentation is generated using the `tools/doc/generate.js` program. -The HTML template is located at `doc/template.html`. \ No newline at end of file +documentation is generated using the `bin/doc/generate.js` program. +The HTML template is located at `doc/template.html`. From f217e29071a6f097b8f50d15762df9b22428e3ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20Laxstr=C3=B6m?= Date: Thu, 29 Dec 2016 08:24:55 +0100 Subject: [PATCH 003/102] Localisation updates from https://translatewiki.net. --- src/locales/diq.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/locales/diq.json b/src/locales/diq.json index e1546e941..1459e44d9 100644 --- a/src/locales/diq.json +++ b/src/locales/diq.json @@ -4,7 +4,8 @@ "Erdemaslancan", "Gorizon", "Mirzali", - "Kumkumuk" + "Kumkumuk", + "1917 Ekim Devrimi" ] }, "index.newPad": "Pedo newe", @@ -25,7 +26,7 @@ "pad.toolbar.savedRevision.title": "Çımraviyarnayışi qeyd ke", "pad.toolbar.settings.title": "Sazkerdışi", "pad.toolbar.embed.title": "Na bloknot degusn u bıhesrne", - "pad.toolbar.showusers.title": "Na bloknot de karbera bıasne", + "pad.toolbar.showusers.title": "Karbera ena bloknot dı bımotné", "pad.colorpicker.save": "Qeyd ke", "pad.colorpicker.cancel": "Bıtexelne", "pad.loading": "Bar beno...", From deed74c8c848745cc5f3d8c4c6ee5db82e6a5592 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20Laxstr=C3=B6m?= Date: Mon, 2 Jan 2017 09:00:13 +0100 Subject: [PATCH 004/102] Localisation updates from https://translatewiki.net. --- src/locales/diq.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/locales/diq.json b/src/locales/diq.json index 1459e44d9..b0e1af5f6 100644 --- a/src/locales/diq.json +++ b/src/locales/diq.json @@ -5,7 +5,8 @@ "Gorizon", "Mirzali", "Kumkumuk", - "1917 Ekim Devrimi" + "1917 Ekim Devrimi", + "Gırd" ] }, "index.newPad": "Pedo newe", @@ -115,7 +116,7 @@ "timeslider.unnamedauthors": "{{num}} unnamed {[plural(num) zu: nuştoğ, zewbi: nustoği ]}", "pad.savedrevs.marked": "Eno vurriyayış henda qeyd bıyaye yew vurriyayış deyne nışan bıyo", "pad.savedrevs.timeslider": "Xızberê zemani ziyer kerdış ra şıma şenê revizyonanê qeyd bıyayan bıvinê", - "pad.userlist.entername": "Nameyê xo cıkewe", + "pad.userlist.entername": "Namey xo cıkewe", "pad.userlist.unnamed": "Name nébıyo", "pad.userlist.guest": "Meyman", "pad.userlist.deny": "Red ke", From b2d9f57338b22cb694adae81c7ec7c1467705ce2 Mon Sep 17 00:00:00 2001 From: Luiza Pagliari Date: Thu, 12 Jan 2017 12:31:42 -0200 Subject: [PATCH 005/102] [fix] Consider line attribs of plugins when building changesets When checking the places on text that are identical between content before and after a changeset, we were considering only the standard (Etherpad-core) attributes, and not taking into account attributes created by the plugins. One consequence was that the '*' marker of lines with line attribs were being kept, even when the new lines have different line attribs. See #3118 for more details. Fix #3118. --- src/static/js/ace2_inner.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/static/js/ace2_inner.js b/src/static/js/ace2_inner.js index 0970666eb..f44a6583a 100644 --- a/src/static/js/ace2_inner.js +++ b/src/static/js/ace2_inner.js @@ -1782,9 +1782,9 @@ function Ace2Inner(){ return !!STYLE_ATTRIBS[aname]; } - function isIncorpedAttribute(aname) + function isOtherIncorpedAttribute(aname) { - return ( !! STYLE_ATTRIBS[aname]) || ( !! OTHER_INCORPED_ATTRIBS[aname]); + return !!OTHER_INCORPED_ATTRIBS[aname]; } function insertDomLines(nodeToAddAfter, infoStructs, isTimeUp) @@ -2526,7 +2526,6 @@ function Ace2Inner(){ function doIncorpLineSplice(startLine, deleteCount, newLineEntries, lineAttribs, hints) { - var startOldChar = rep.lines.offsetOfIndex(startLine); var endOldChar = rep.lines.offsetOfIndex(startLine + deleteCount); @@ -2760,7 +2759,7 @@ function Ace2Inner(){ { function incorpedAttribFilter(anum) { - return isStyleAttribute(rep.apool.getAttribKey(anum)); + return !isOtherIncorpedAttribute(rep.apool.getAttribKey(anum)); } function attribRuns(attribs) From 520f257ed19cb410dbbf0fc3017869bd544a8173 Mon Sep 17 00:00:00 2001 From: Luiza Pagliari Date: Thu, 12 Jan 2017 13:04:32 -0200 Subject: [PATCH 006/102] [chore] Use helper plugin when running tests on Travis This plugin allows us to test code related to plugins, like testing issues that only happen when we have plugins using line attribs, for example (see #3118). --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 4cdf63837..911ea8bad 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ node_js: install: - "bin/installDeps.sh" - "export GIT_HASH=$(git rev-parse --verify --short HEAD)" + - "npm install ep_test_line_attrib" before_script: - "tests/frontend/travis/sauce_tunnel.sh" script: From 6e1bf9dc90c8874405a4b572ec450d55247fd86d Mon Sep 17 00:00:00 2001 From: tpltnt Date: Thu, 12 Jan 2017 20:50:31 +0100 Subject: [PATCH 007/102] added curl as dependency --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index afec716e9..d6221250d 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ If cloning to a subdirectory within another project, you may need to do the foll You'll need gzip, git, curl, libssl develop libraries, python and gcc. - *For Debian/Ubuntu*: `apt-get install gzip git curl python libssl-dev pkg-config build-essential` - *For Fedora/CentOS*: `yum install gzip git curl python openssl-devel && yum groupinstall "Development Tools"` -- *For FreeBSD*: `portinstall node, npm, git (optional)` +- *For FreeBSD*: `portinstall node, npm, curl, git (optional)` Additionally, you'll need [node.js](http://nodejs.org) installed, Ideally the latest stable version, we recommend installing/compiling nodejs from source (avoiding apt). From d48395089c0fad5e9a1fa83a05950fc35372e926 Mon Sep 17 00:00:00 2001 From: Sjoerd Langkemper Date: Tue, 17 Jan 2017 14:59:24 +0100 Subject: [PATCH 008/102] Update called from for two hooks `expressCreateServer` and `expressConfigure` are called from `express.js`, not from `server.js`. --- doc/api/hooks_server-side.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/api/hooks_server-side.md b/doc/api/hooks_server-side.md index 5775c49d9..f894fec90 100644 --- a/doc/api/hooks_server-side.md +++ b/doc/api/hooks_server-side.md @@ -36,7 +36,7 @@ Things in context: None This function is called after a specific plugin is initialized. This would probably be more useful than the previous two functions if you only wanted to add in features to one specific plugin. ## expressConfigure -Called from: src/node/server.js +Called from: src/node/hooks/express.js Things in context: @@ -45,7 +45,7 @@ Things in context: This is a helpful hook for changing the behavior and configuration of the application. It's called right after the application gets configured. ## expressCreateServer -Called from: src/node/server.js +Called from: src/node/hooks/express.js Things in context: From 21a6e66e25a468323976349855397a599e1f52b9 Mon Sep 17 00:00:00 2001 From: Sjoerd Langkemper Date: Thu, 26 Jan 2017 09:59:09 +0100 Subject: [PATCH 009/102] Remove deprecated comment The session key is currently stored in SESSIONKEY.txt, so it is no longer reset every time the server starts. --- src/node/hooks/express/webaccess.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node/hooks/express/webaccess.js b/src/node/hooks/express/webaccess.js index c53eb1d1a..190021a3e 100644 --- a/src/node/hooks/express/webaccess.js +++ b/src/node/hooks/express/webaccess.js @@ -116,7 +116,7 @@ exports.expressConfigure = function (hook_name, args, cb) { if (!exports.sessionStore) { exports.sessionStore = new ueberStore(); - exports.secret = settings.sessionKey; // Isn't this being reset each time the server spawns? + exports.secret = settings.sessionKey; } args.app.sessionStore = exports.sessionStore; From 02bd4a31afc09e594dd2d305ca6eb91065c9f798 Mon Sep 17 00:00:00 2001 From: Luiza Pagliari Date: Fri, 3 Feb 2017 06:47:33 -0200 Subject: [PATCH 010/102] [fix] Fix drag and drop tests for IE --- tests/frontend/specs/drag_and_drop.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/frontend/specs/drag_and_drop.js b/tests/frontend/specs/drag_and_drop.js index bcec0bd29..821d3aacc 100644 --- a/tests/frontend/specs/drag_and_drop.js +++ b/tests/frontend/specs/drag_and_drop.js @@ -154,7 +154,15 @@ describe('drag and drop', function() { var $target = getLine(targetLineNumber); $target.sendkeys('{selectall}{rightarrow}{leftarrow}'); - // insert content - innerDocument.execCommand('insertHTML', false, draggedHtml); + // Insert content. + // Based on http://stackoverflow.com/a/6691294, to be IE-compatible + var range = innerDocument.getSelection().getRangeAt(0); + var frag = innerDocument.createDocumentFragment(); + var el = innerDocument.createElement('div'); + el.innerHTML = draggedHtml; + while (el.firstChild) { + frag.appendChild(el.firstChild); + } + range.insertNode(frag); } }); From 306e63c3f50915941933f2a81234fa7e2cdd48bc Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 6 Feb 2017 07:52:00 +0100 Subject: [PATCH 011/102] Localisation updates from https://translatewiki.net. --- src/locales/az.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/locales/az.json b/src/locales/az.json index 48f0f8412..800c22e5c 100644 --- a/src/locales/az.json +++ b/src/locales/az.json @@ -5,7 +5,8 @@ "Khan27", "Mushviq Abdulla", "Wertuose", - "Mastizada" + "Mastizada", + "Archaeodontosaurus" ] }, "index.newPad": "Yeni lövhə", @@ -114,6 +115,7 @@ "timeslider.month.december": "Dekabr", "timeslider.unnamedauthors": "{{num}} adsız {[plural(num) one: müəllif, other: müəllif]}", "pad.savedrevs.marked": "Bu versiya indi yaddaşa saxlanmış kimi nişanlandı", + "pad.savedrevs.timeslider": "Siz görə bilərsiniz saxlanılan versiyası miqyasında vaxt", "pad.userlist.entername": "Adınızı daxil edin", "pad.userlist.unnamed": "adsız", "pad.userlist.guest": "Qonaq", From d1e6c8492d3935552100dd9023d3b16fd180fa76 Mon Sep 17 00:00:00 2001 From: joassouza Date: Tue, 7 Feb 2017 13:04:22 -0200 Subject: [PATCH 012/102] Fix minification of code --- src/node/utils/Minify.js | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/node/utils/Minify.js b/src/node/utils/Minify.js index 806523105..2be1fea42 100644 --- a/src/node/utils/Minify.js +++ b/src/node/utils/Minify.js @@ -23,9 +23,9 @@ var ERR = require("async-stacktrace"); var settings = require('./Settings'); var async = require('async'); var fs = require('fs'); +var StringDecoder = require('string_decoder').StringDecoder; var CleanCSS = require('clean-css'); -var jsp = require("uglify-js").parser; -var pro = require("uglify-js").uglify; +var uglifyJS = require("uglify-js"); var path = require('path'); var plugins = require("ep_etherpad-lite/static/js/pluginfw/plugins"); var RequireKernel = require('etherpad-require-kernel'); @@ -375,7 +375,9 @@ function getFileCompressed(filename, contentType, callback) { callback(error, content); } else if (contentType == 'text/javascript') { try { - content = compressJS(content); + var decoder = new StringDecoder('utf8'); + var code = decoder.write(content); // convert from buffer to string + content = uglifyJS.minify(code, {fromString: true}).code; } catch (error) { // silence } @@ -398,14 +400,6 @@ function getFile(filename, callback) { } } -function compressJS(content) -{ - var ast = jsp.parse(content); // parse code and get the initial AST - ast = pro.ast_mangle(ast); // get a new AST with mangled names - ast = pro.ast_squeeze(ast); // get an AST with compression optimizations - return pro.gen_code(ast); // compressed code here -} - function compressCSS(filename, content, callback) { try { From 0025613ba6d954572b88f9797b60f3b2541b8b86 Mon Sep 17 00:00:00 2001 From: joassouza Date: Tue, 7 Feb 2017 15:06:49 -0200 Subject: [PATCH 013/102] Refactor code --- src/node/utils/Minify.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/node/utils/Minify.js b/src/node/utils/Minify.js index 2be1fea42..a56e347db 100644 --- a/src/node/utils/Minify.js +++ b/src/node/utils/Minify.js @@ -375,9 +375,7 @@ function getFileCompressed(filename, contentType, callback) { callback(error, content); } else if (contentType == 'text/javascript') { try { - var decoder = new StringDecoder('utf8'); - var code = decoder.write(content); // convert from buffer to string - content = uglifyJS.minify(code, {fromString: true}).code; + content = compressJS(content); } catch (error) { // silence } @@ -400,6 +398,14 @@ function getFile(filename, callback) { } } +function compressJS(content) +{ + var decoder = new StringDecoder('utf8'); + var code = decoder.write(content); // convert from buffer to string + var codeMinified = uglifyJS.minify(code, {fromString: true}).code; + return codeMinified; +} + function compressCSS(filename, content, callback) { try { From 92be6561137bb9db1569910faaff25c0607c4212 Mon Sep 17 00:00:00 2001 From: Luiza Pagliari Date: Mon, 20 Feb 2017 06:02:31 -0300 Subject: [PATCH 014/102] [test] Fix helper tests for IE --- tests/frontend/specs/helper.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/tests/frontend/specs/helper.js b/tests/frontend/specs/helper.js index bb47f4dcd..7270d4798 100644 --- a/tests/frontend/specs/helper.js +++ b/tests/frontend/specs/helper.js @@ -101,16 +101,17 @@ describe("the test helper", function(){ // function to support tests, use a single way to represent whitespaces var cleanText = function(text){ return text - .replace(/\n/gi, "\\\\n") // avoid \n to be replaced by \s on next line - .replace(/\s/gi, " ") - .replace(/\\\\n/gi, "\n"); // move back \n to its original state + // IE replaces line breaks with a whitespace, so we need to unify its behavior + // for other browsers, to have all tests running for all browsers + .replace(/\n/gi, " ") + .replace(/\s/gi, " "); } before(function(done){ helper.newPad(function() { // create some lines to be used on the tests var $firstLine = helper.padInner$("div").first(); - $firstLine.sendkeys("{selectall}some{enter}short{enter}lines{enter}to test{enter}"); + $firstLine.sendkeys("{selectall}some{enter}short{enter}lines{enter}to test{enter}{enter}"); // wait for lines to be split helper.waitFor(function(){ @@ -135,7 +136,7 @@ describe("the test helper", function(){ helper.selectLines($startLine, $endLine, startOffset, endOffset); var selection = inner$.document.getSelection(); - expect(cleanText(selection.toString())).to.be("ort \nlines \nto t"); + expect(cleanText(selection.toString())).to.be("ort lines to t"); done(); }); @@ -153,7 +154,7 @@ describe("the test helper", function(){ helper.selectLines($startLine, $endLine, startOffset, endOffset); var selection = inner$.document.getSelection(); - expect(cleanText(selection.toString())).to.be("ort \nlines \nto test\n"); + expect(cleanText(selection.toString())).to.be("ort lines to test"); done(); }); @@ -171,7 +172,7 @@ describe("the test helper", function(){ helper.selectLines($startLine, $endLine, startOffset, endOffset); var selection = inner$.document.getSelection(); - expect(cleanText(selection.toString())).to.be("ort \nlines \n"); + expect(cleanText(selection.toString())).to.be("ort lines "); done(); }); @@ -189,7 +190,7 @@ describe("the test helper", function(){ helper.selectLines($startLine, $endLine, startOffset, endOffset); var selection = inner$.document.getSelection(); - expect(cleanText(selection.toString())).to.be("ort \nlines \nto test"); + expect(cleanText(selection.toString())).to.be("ort lines to test"); done(); }); @@ -204,7 +205,7 @@ describe("the test helper", function(){ helper.selectLines($startLine, $endLine); var selection = inner$.document.getSelection(); - expect(cleanText(selection.toString())).to.be("short \nlines \nto test"); + expect(cleanText(selection.toString())).to.be("short lines to test"); done(); }); From 15cda0fde6b3b5794b26331f36ab04413be0ee0e Mon Sep 17 00:00:00 2001 From: Luiza Pagliari Date: Mon, 20 Feb 2017 06:03:56 -0300 Subject: [PATCH 015/102] [refactor] Use better way to select a single line --- tests/frontend/specs/helper.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/frontend/specs/helper.js b/tests/frontend/specs/helper.js index 7270d4798..863f7a92c 100644 --- a/tests/frontend/specs/helper.js +++ b/tests/frontend/specs/helper.js @@ -115,7 +115,7 @@ describe("the test helper", function(){ // wait for lines to be split helper.waitFor(function(){ - var $fourthLine = helper.padInner$("div").slice(3,4); + var $fourthLine = helper.padInner$("div").eq(3); return $fourthLine.text() === "to test"; }).done(done); }); @@ -130,8 +130,8 @@ describe("the test helper", function(){ var endOffset = 4; var $lines = inner$("div"); - var $startLine = $lines.slice(1,2); - var $endLine = $lines.slice(3,4); + var $startLine = $lines.eq(1); + var $endLine = $lines.eq(3); helper.selectLines($startLine, $endLine, startOffset, endOffset); @@ -148,8 +148,8 @@ describe("the test helper", function(){ var endOffset = 1; var $lines = inner$("div"); - var $startLine = $lines.slice(1,2); - var $endLine = $lines.slice(4,5); + var $startLine = $lines.eq(1); + var $endLine = $lines.eq(4); helper.selectLines($startLine, $endLine, startOffset, endOffset); @@ -166,8 +166,8 @@ describe("the test helper", function(){ var endOffset = 0; var $lines = inner$("div"); - var $startLine = $lines.slice(1,2); - var $endLine = $lines.slice(3,4); + var $startLine = $lines.eq(1); + var $endLine = $lines.eq(3); helper.selectLines($startLine, $endLine, startOffset, endOffset); @@ -184,8 +184,8 @@ describe("the test helper", function(){ var endOffset = 50; var $lines = inner$("div"); - var $startLine = $lines.slice(1,2); - var $endLine = $lines.slice(3,4); + var $startLine = $lines.eq(1); + var $endLine = $lines.eq(3); helper.selectLines($startLine, $endLine, startOffset, endOffset); @@ -199,8 +199,8 @@ describe("the test helper", function(){ var inner$ = helper.padInner$; var $lines = inner$("div"); - var $startLine = $lines.slice(1,2); - var $endLine = $lines.slice(3,4); + var $startLine = $lines.eq(1); + var $endLine = $lines.eq(3); helper.selectLines($startLine, $endLine); From 2b96a961e3bb70cf574c9248eda16f460809e571 Mon Sep 17 00:00:00 2001 From: Luiza Pagliari Date: Mon, 20 Feb 2017 06:14:27 -0300 Subject: [PATCH 016/102] [fix] Remove extra whitespace on helper tests for IE --- tests/frontend/specs/helper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/frontend/specs/helper.js b/tests/frontend/specs/helper.js index 863f7a92c..8520769aa 100644 --- a/tests/frontend/specs/helper.js +++ b/tests/frontend/specs/helper.js @@ -103,7 +103,7 @@ describe("the test helper", function(){ return text // IE replaces line breaks with a whitespace, so we need to unify its behavior // for other browsers, to have all tests running for all browsers - .replace(/\n/gi, " ") + .replace(/\n/gi, "") .replace(/\s/gi, " "); } From 393f651770b800a48d5459395c3cde37ef742d49 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 23 Feb 2017 09:00:01 +0100 Subject: [PATCH 017/102] Localisation updates from https://translatewiki.net. --- src/locales/oc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/locales/oc.json b/src/locales/oc.json index 00944531b..4678de176 100644 --- a/src/locales/oc.json +++ b/src/locales/oc.json @@ -91,7 +91,7 @@ "timeslider.toolbar.exportlink.title": "Exportar", "timeslider.exportCurrent": "Exportar la version actuala en :", "timeslider.version": "Version {{version}}", - "timeslider.saved": "Enregistrat lo {{day}} {{month}} {{year}}", + "timeslider.saved": "Enregistrat lo {{day}} de {{month}} de {{year}}", "timeslider.playPause": "Lectura / Pausa dels contenguts del pad", "timeslider.backRevision": "Recular d’una revision dins aqueste pad", "timeslider.forwardRevision": "Avançar d’una revision dins aqueste pad", From 95151093080433a21e2a1abf4dfbca76f109069f Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 27 Feb 2017 07:48:12 +0100 Subject: [PATCH 018/102] Localisation updates from https://translatewiki.net. --- src/locales/ta.json | 77 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 src/locales/ta.json diff --git a/src/locales/ta.json b/src/locales/ta.json new file mode 100644 index 000000000..c0a7cdc08 --- /dev/null +++ b/src/locales/ta.json @@ -0,0 +1,77 @@ +{ + "@metadata": { + "authors": [ + "Balajijagadesh", + "ElangoRamanujam", + "Sank" + ] + }, + "index.newPad": "புதிய அட்டை", + "index.createOpenPad": "அல்லது பெயருடன் ஒரு அட்டையை உருவாக்கு/திற", + "pad.toolbar.bold.title": "தடித்த (Ctrl+B)", + "pad.toolbar.italic.title": "சாய்ந்த (Ctrl+l)", + "pad.toolbar.underline.title": "அடிக்கோடு (Ctrl-U)", + "pad.toolbar.strikethrough.title": "குறுக்குக்கோடு (Ctrl+5)", + "pad.toolbar.timeslider.title": "நேர வழுக்கி", + "pad.toolbar.settings.title": "அமைப்புகள்", + "pad.toolbar.embed.title": "இவ்வட்டையை பகிர் மற்றும் பதி", + "pad.toolbar.showusers.title": "இவ்வட்டையின் பயனர்களை காட்டவும்", + "pad.colorpicker.save": "சேமி", + "pad.colorpicker.cancel": "இரத்து செய்", + "pad.loading": "ஏற்றப்படுகிறது...", + "pad.passwordRequired": "இவ்வட்டையை அணுக தங்களுக்கு ஒரு கடவுச்சொல் தேவைப்படும்", + "pad.permissionDenied": "இவ்வட்டையை அணுக தங்களுக்கு அனுமதி இல்லை", + "pad.wrongPassword": "தங்கள் கடவுச்சொல் தவறானது", + "pad.settings.padSettings": "அட்டை அமைவுகள்", + "pad.settings.myView": "என் பார்வை", + "pad.settings.stickychat": "திரையில் எப்பொழுதும் அரட்டை", + "pad.settings.chatandusers": "அரட்டை மற்றும் பயனர்களை காட்டுக", + "pad.settings.colorcheck": "ஆசிரியர் நிறங்கள்", + "pad.settings.linenocheck": "வரி எண்கள்", + "pad.settings.fontType": "எழுத்துரு வகை:", + "pad.settings.globalView": "உலக பார்வை", + "pad.settings.language": "மொழி:", + "pad.importExport.import_export": "இறக்குமதி/ஏற்றுமதி", + "pad.importExport.importSuccessful": "வெற்றி!", + "pad.modals.connected": "இணைக்கப்பட்டது.", + "pad.modals.initsocketfail": "வழங்கியை தொடர்பு கொள்ளமுடியவில்லை", + "pad.modals.deleted": "நீக்கப்பட்டது", + "pad.modals.deleted.explanation": "இந்த அட்டை நீக்கப்பட்டது.", + "pad.modals.disconnected": "தாங்கள் துண்டிக்கப்பட்டுள்ளீர்கள்", + "pad.modals.disconnected.explanation": "வழங்கியின் தொடர்பு தொலைந்து", + "pad.share": "இவ்வட்டையை பகிர்க", + "pad.share.readonly": "வாசிக்க மாத்திரம்", + "pad.share.link": "இணைப்பு", + "pad.share.emebdcode": "உரலியை பதிக", + "pad.chat": "அரட்டை", + "pad.chat.title": "இவ்வட்டைக்கு அரட்டையை திறக்கவும்", + "pad.chat.loadmessages": "மேலும் தகவல்களை பதிவேற்றவும்", + "timeslider.pageTitle": "{{appTitle}} நேரவழுக்கி", + "timeslider.toolbar.returnbutton": "அட்டைக்கு திரும்பவும்", + "timeslider.toolbar.authors": "ஆசிரியர்கள்:", + "timeslider.toolbar.authorsList": "ஆசிரியர்கள் இல்லை", + "timeslider.toolbar.exportlink.title": "ஏற்றுமதி செய்க", + "timeslider.version": "பதிப்பு {{version}}", + "timeslider.month.january": "சனவரி", + "timeslider.month.february": "பெப்ரவரி", + "timeslider.month.march": "மார்ச்", + "timeslider.month.april": "ஏப்ரல்", + "timeslider.month.may": "மே", + "timeslider.month.june": "சூன்", + "timeslider.month.july": "சூலை", + "timeslider.month.august": "ஆகஸ்ட்", + "timeslider.month.september": "செப்டம்பர்", + "timeslider.month.october": "அக்டோபர்", + "timeslider.month.november": "நவம்பர்", + "timeslider.month.december": "டிசம்பர்", + "pad.userlist.entername": "உங்கள் பெயரை உள்ளிடுக", + "pad.userlist.unnamed": "பெயரிடப்படாதது", + "pad.userlist.guest": "விருந்தினர்", + "pad.userlist.deny": "மறுக்கவும்", + "pad.userlist.approve": "ஒப்புதல் அளிக்கவும்", + "pad.impexp.importbutton": "இப்பொழுது இறக்குக", + "pad.impexp.importing": "இறக்குகிறது...", + "pad.impexp.uploadFailed": "பதிவேற்றம் தோல்வியடைந்தது, தயவுசெய்து மீண்டும் முயலவும்.", + "pad.impexp.importfailed": "இறக்குமதி தோல்வியடைந்தது", + "pad.impexp.copypaste": "படியெடுத்து ஒட்டுக" +} From bc0eff6dd0b0a081fe34ad3c5046049caabb2ecb Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 6 Mar 2017 08:49:04 +0100 Subject: [PATCH 019/102] Localisation updates from https://translatewiki.net. --- src/locales/te.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/locales/te.json b/src/locales/te.json index 198782062..846ced8e3 100644 --- a/src/locales/te.json +++ b/src/locales/te.json @@ -14,7 +14,7 @@ "pad.toolbar.bold.title": "మందం", "pad.toolbar.italic.title": "వాలు అక్షరాలు", "pad.toolbar.underline.title": "క్రిందగీత", - "pad.toolbar.strikethrough.title": "కొట్టివేత", + "pad.toolbar.strikethrough.title": "కొట్టివేత (Ctrl+5)", "pad.toolbar.ol.title": "నిర్ధేశింపబడిన జాబితా", "pad.toolbar.ul.title": "అనిర్దేశిత జాబితా, ( క్రమపద్ధతి లేని జాబితా )", "pad.toolbar.undo.title": "చేయవద్దు", From eeb8e82771d3c5b57262bfd753fe95ae79862ba4 Mon Sep 17 00:00:00 2001 From: Adam Niederer Date: Sat, 11 Mar 2017 21:27:34 -0500 Subject: [PATCH 020/102] Remove an extra space --- doc/localization.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/localization.md b/doc/localization.md index 15c4d59dc..4d8fd894c 100644 --- a/doc/localization.md +++ b/doc/localization.md @@ -1,5 +1,5 @@ # Localization -Etherpad provides a multi-language user interface, that's apart from your users' content, so users from different countries can collaborate on a single document, while still having the user interface displayed in their mother tongue. +Etherpad provides a multi-language user interface, that's apart from your users' content, so users from different countries can collaborate on a single document, while still having the user interface displayed in their mother tongue. ## Translating From a5e576c5641867a20e1f47cf384f4c9e56f166cf Mon Sep 17 00:00:00 2001 From: Adam Niederer Date: Sat, 11 Mar 2017 21:30:32 -0500 Subject: [PATCH 021/102] Grammar fix --- doc/localization.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/localization.md b/doc/localization.md index 15c4d59dc..3ec2b88d0 100644 --- a/doc/localization.md +++ b/doc/localization.md @@ -31,7 +31,7 @@ Translations will be send back to us regularly and will eventually appear in the Each translation consists of a key (the id of the string that is to be translated) and the translated string. Terms in curly braces must not be touched but left as they are, since they represent a dynamically changing part of the string like a variable. Imagine a message welcoming a user: `Welcome, {{userName}}!` would be translated as `Ahoy, {{userName}}!` in pirate. ### Client-side -We use a `language` cookie to save your language settings if you change them. If you don't, we autodetect your locale using information from your browser. Now, that we know your preferred language this information is feeded into a very nice library called [html10n.js](https://github.com/marcelklehr/html10n.js), which loads the appropriate translations and applies them to our templates, providing translation params, pluralization, include rules and even a nice javascript API along the way. +We use a `language` cookie to save your language settings if you change them. If you don't, we autodetect your locale using information from your browser. Now, that we know your preferred language this information is fed into a very nice library called [html10n.js](https://github.com/marcelklehr/html10n.js), which loads the appropriate translations and applies them to our templates, providing translation params, pluralization, include rules and even a nice javascript API along the way. From 6d279f0ee16321d2a350619d55661a0524dc276c Mon Sep 17 00:00:00 2001 From: Adam Niederer Date: Sat, 11 Mar 2017 21:34:34 -0500 Subject: [PATCH 022/102] Spelling fix Also removes an extra space --- doc/api/hooks_server-side.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/api/hooks_server-side.md b/doc/api/hooks_server-side.md index f894fec90..8a4ad978c 100644 --- a/doc/api/hooks_server-side.md +++ b/doc/api/hooks_server-side.md @@ -72,7 +72,7 @@ Available blocks in `pad.html` are: * `editbarMenuRight` - right tool bar * `afterEditbar` - allows you to add stuff immediately after the toolbar * `userlist` - the contents of the userlist dropdown - * `loading` - the intial loading message + * `loading` - the initial loading message * `mySettings` - the left column of the settings dropdown ("My view"); intended for adding checkboxes only * `mySettings.dropdowns` - add your dropdown settings here * `globalSettings` - the right column of the settings dropdown ("Global view") @@ -104,7 +104,7 @@ Things in context: Here you can add custom toolbar items that will be available in the toolbar config in `settings.json`. For more about the toolbar controller see the API section. -Usage examples: +Usage examples: * [https://github.com/tiblu/ep_authorship_toggle]() From 867e2d69d44943a930b2d858c9af19f578a3bf43 Mon Sep 17 00:00:00 2001 From: Adam Niederer Date: Sat, 11 Mar 2017 21:35:00 -0500 Subject: [PATCH 023/102] Spelling, grammar, and style improvements --- doc/localization.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/localization.md b/doc/localization.md index 3ec2b88d0..e74d9a958 100644 --- a/doc/localization.md +++ b/doc/localization.md @@ -31,7 +31,7 @@ Translations will be send back to us regularly and will eventually appear in the Each translation consists of a key (the id of the string that is to be translated) and the translated string. Terms in curly braces must not be touched but left as they are, since they represent a dynamically changing part of the string like a variable. Imagine a message welcoming a user: `Welcome, {{userName}}!` would be translated as `Ahoy, {{userName}}!` in pirate. ### Client-side -We use a `language` cookie to save your language settings if you change them. If you don't, we autodetect your locale using information from your browser. Now, that we know your preferred language this information is fed into a very nice library called [html10n.js](https://github.com/marcelklehr/html10n.js), which loads the appropriate translations and applies them to our templates, providing translation params, pluralization, include rules and even a nice javascript API along the way. +We use a `language` cookie to save your language settings if you change them. If you don't, we autodetect your locale using information from your browser. Then, the preferred language is fed into a library called [html10n.js](https://github.com/marcelklehr/html10n.js), which loads the appropriate translations and applies them to our templates. Its features include translation params, pluralization, include rules and a nice javascript API. @@ -79,7 +79,7 @@ alert(window._('pad.chat')); } ``` -Everytime the http server is started, it will auto-detect your messages and merge them automatically with the core messages. +Every time the http server is started, it will auto-detect your messages and merge them automatically with the core messages. ### Overwrite core messages From 52d5fc713e785d99d6fa1704e22709e305ffca07 Mon Sep 17 00:00:00 2001 From: Adam Niederer Date: Sat, 11 Mar 2017 21:36:37 -0500 Subject: [PATCH 024/102] Spelling fixes --- doc/database.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/database.md b/doc/database.md index de3e9f547..9f6126d63 100644 --- a/doc/database.md +++ b/doc/database.md @@ -6,7 +6,7 @@ A list of all existing groups (a JSON object with groupIDs as keys and `1` as values). ### pad:$PADID -Saves all informations about pads +Contains all information about pads * **atext** - the latest attributed text * **pool** - the attribute pool @@ -24,10 +24,10 @@ Saves a revision $REVNUM of pad $PADID * **changeset** - the changeset of this revision ### pad:$PADID:chat:$CHATNUM -Saves a chatentry with num $CHATNUM of pad $PADID +Saves a chat entry with num $CHATNUM of pad $PADID * **text** - the text of this chat entry -* **userId** - the autorID of this chat entry +* **userId** - the authorID of this chat entry * **time** - the timestamp of this chat entry ### pad2readonly:$PADID @@ -43,9 +43,9 @@ Information about an author * **colorID** - the colorID of this author as shown in the pad ### mapper2group:$MAPPER -Maps an external application identifier to an internal group +Maps an external application identifier to an internal group ### mapper2author:$MAPPER -Maps an external application identifier to an internal author +Maps an external application identifier to an internal author ### group:$GROUPID a group of pads From 7520377026149ff9a65018062167956291fde48f Mon Sep 17 00:00:00 2001 From: Adam Niederer Date: Sat, 11 Mar 2017 21:38:50 -0500 Subject: [PATCH 025/102] Spelling fixes --- doc/api/editorInfo.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/api/editorInfo.md b/doc/api/editorInfo.md index afb790b99..7cbe3fcd0 100644 --- a/doc/api/editorInfo.md +++ b/doc/api/editorInfo.md @@ -69,9 +69,9 @@ This function replaces a range (from y1 to y2) with `newText`. ## editorInfo.ace_renumberList(lineNum) If you delete a line, calling this method will fix the line numbering. ## editorInfo.ace_doReturnKey() -Forces a return key at the current carret position. +Forces a return key at the current caret position. ## editorInfo.ace_isBlockElement(element) -Returns true if your passed elment is registered as a block element +Returns true if your passed element is registered as a block element ## editorInfo.ace_getLineListType(lineNum) Returns the line's html list type. ## editorInfo.ace_caretLine() From cb8fe92df7fdd7dc78bf98e3168f5d1bda664f93 Mon Sep 17 00:00:00 2001 From: Adam Niederer Date: Sat, 11 Mar 2017 22:09:49 -0500 Subject: [PATCH 026/102] Fix typo --- doc/api/editbar.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/api/editbar.md b/doc/api/editbar.md index d4ad4c64d..d297eb255 100644 --- a/doc/api/editbar.md +++ b/doc/api/editbar.md @@ -1,5 +1,5 @@ # Editbar -srf/static/js/pad_editbar.js +src/static/js/pad_editbar.js ## isEnabled() @@ -25,4 +25,4 @@ toolbar.registerAceCommand("insertorderedlist", function (cmd, ace) { Ties a `div.popup` where `id` equals `dropdown` to a `command` fired by clicking a button. ## triggerCommand(cmd[, item]) -Triggers a command (optionally with some internal representation of the toolbar item that triggered it). \ No newline at end of file +Triggers a command (optionally with some internal representation of the toolbar item that triggered it). From 5eadc715a6a3ad64a6c5e1a484ad092a070b80c7 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 13 Mar 2017 08:08:38 +0100 Subject: [PATCH 027/102] Localisation updates from https://translatewiki.net. --- src/locales/sk.json | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/locales/sk.json b/src/locales/sk.json index 445adc005..b1dc0a202 100644 --- a/src/locales/sk.json +++ b/src/locales/sk.json @@ -4,7 +4,8 @@ "Teslaton", "Kusavica", "Rudko", - "Mark" + "Mark", + "Lexected" ] }, "index.newPad": "Nový Pad", @@ -29,12 +30,14 @@ "pad.colorpicker.save": "Uložiť", "pad.colorpicker.cancel": "Zrušiť", "pad.loading": "Načítava sa...", + "pad.noCookie": "Cookie nebolo možné nájsť. Povoľte prosím cookies vo vašom prehliadači.", "pad.passwordRequired": "Prístup k tomuto Padu je chránený heslom", "pad.permissionDenied": "Ľutujeme, nemáte oprávnenie pristupovať k tomuto Padu", "pad.wrongPassword": "Nesprávne heslo", "pad.settings.padSettings": "Nastavenia Padu", "pad.settings.myView": "Vlastný pohľad", "pad.settings.stickychat": "Chat stále na obrazovke", + "pad.settings.chatandusers": "Zobraziť chat a užívateľov", "pad.settings.colorcheck": "Farby autorstva", "pad.settings.linenocheck": "Čísla riadkov", "pad.settings.rtlcheck": "Čítať obsah sprava doľava?", @@ -93,6 +96,9 @@ "timeslider.exportCurrent": "Exportovať aktuálnu verziu ako:", "timeslider.version": "Verzia {{version}}", "timeslider.saved": "Uložené {{day}}. {{month}} {{year}}", + "timeslider.playPause": "Pustiť / Pozastaviť obsah padu", + "timeslider.backRevision": "Ísť v tomto pade a revíziu späť", + "timeslider.forwardRevision": "Ísť v tomto pade o revíziu vpred", "timeslider.dateformat": "{{day}}. {{month}} {{year}} {{hours}}:{{minutes}}:{{seconds}}", "timeslider.month.january": "januára", "timeslider.month.february": "februára", @@ -108,6 +114,7 @@ "timeslider.month.december": "decembra", "timeslider.unnamedauthors": "{{num}} {[ plural(num) one: nemenovaný autor, few: nemenovaní autori, other: nemenovaných autorov ]}", "pad.savedrevs.marked": "Táto revízia bola označená ako uložená", + "pad.savedrevs.timeslider": "Návštevou časovej osi môžete zobraziť uložené revízie", "pad.userlist.entername": "Zadajte svoje meno", "pad.userlist.unnamed": "nemenovaný", "pad.userlist.guest": "Hosť", @@ -118,6 +125,7 @@ "pad.impexp.importing": "Prebieha import...", "pad.impexp.confirmimport": "Import súboru prepíše celý súčasný obsah Padu. Skutočne si želáte vykonať túto akciu?", "pad.impexp.convertFailed": "Tento súbor nie je možné importovať. Použite prosím iný formát súboru alebo nakopírujte text manuálne", + "pad.impexp.padHasData": "Nebolo možné importovať tento súbor, pretože tento pad už bol pozmenený. Importujte prosím súbor do nového padu", "pad.impexp.uploadFailed": "Nahrávanie zlyhalo, skúste to prosím znovu", "pad.impexp.importfailed": "Import zlyhal", "pad.impexp.copypaste": "Vložte prosím kópiu cez schránku", From ce2c74d120689b750cb2ab5aac79599872b3ba77 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 20 Mar 2017 07:24:19 +0100 Subject: [PATCH 028/102] Localisation updates from https://translatewiki.net. --- src/locales/azb.json | 5 +++++ src/locales/hu.json | 11 ++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/locales/azb.json b/src/locales/azb.json index f8d8f93b8..2e550bc3c 100644 --- a/src/locales/azb.json +++ b/src/locales/azb.json @@ -68,10 +68,14 @@ "pad.modals.initsocketfail": "سرور الده دئییلدیر.", "pad.modals.initsocketfail.explanation": "بیرلشدیریلمه سرور لرینه متصیل اولا بیلمه دی", "pad.modals.slowcommit.explanation": "سرور جواب وئرمه ییر.", + "pad.modals.slowcommit.cause": "بو، شبکه باغلانتیسیندا خطالار اوچون اولا بیلر.", + "pad.modals.corruptPad.explanation": "ال تاپماغا چالیشدیغینیز پد کورلانیبدیر.", + "pad.modals.corruptPad.cause": "بو، غلط سرور تنظیملری یوخسا آیری بیر گوزلنیلمز بیر داورانیشدان عمله گله بیلر. لوطفا سرویس ایداره چیسی ایله تماس توتون.", "pad.modals.deleted": "سیلیندی.", "pad.modals.deleted.explanation": "بۇ یادداشت دفترچه‌سی سیلینیبدیر.", "pad.modals.disconnected": "سیزین باغلانتینیز کسیلیبدیر.", "pad.modals.disconnected.explanation": "سروره باغلانتی کسیلیبدیر.", + "pad.modals.disconnected.cause": "سرور ال چاتماز اولا بیلر. بئله قالیرسا سرویس ایداره چیسینی آییق سالین.", "pad.share": "بو نوت دفترچه سینی پایلاش", "pad.share.readonly": "ساده‌جه اوْخومالی", "pad.share.link": "باغلانتی", @@ -86,6 +90,7 @@ "timeslider.toolbar.exportlink.title": "ائشیگه آپارماق", "timeslider.exportCurrent": "موجود نوسخه نی بو عونوانلا ائشیگه چیخارت:", "timeslider.version": "{{version}} ورژنی", + "timeslider.saved": "ساخلانیلدی {{day}} {{month}}, {{year}}", "timeslider.month.january": "ژانویه", "timeslider.month.february": "فوریه", "timeslider.month.march": "مارس", diff --git a/src/locales/hu.json b/src/locales/hu.json index f34c76caf..828d92e5d 100644 --- a/src/locales/hu.json +++ b/src/locales/hu.json @@ -5,14 +5,15 @@ "Misibacsi", "R-Joe", "Tgr", - "Csega" + "Csega", + "BanKris" ] }, "index.newPad": "Új notesz", "index.createOpenPad": "vagy notesz létrehozása/megnyitása ezzel a névvel:", - "pad.toolbar.bold.title": "Félkövér (Ctrl-B)", - "pad.toolbar.italic.title": "Dőlt (Ctrl-I)", - "pad.toolbar.underline.title": "Aláhúzás (Ctrl-U)", + "pad.toolbar.bold.title": "Félkövér (Ctrl+B)", + "pad.toolbar.italic.title": "Dőlt (Ctrl+I)", + "pad.toolbar.underline.title": "Aláhúzás (Ctrl+U)", "pad.toolbar.strikethrough.title": "Áthúzás (Ctrl+5)", "pad.toolbar.ol.title": "Számozott lista (Ctrl+Shift+N)", "pad.toolbar.ul.title": "Számozatlan lista (Ctrl+Shift+L)", @@ -112,7 +113,7 @@ "timeslider.month.october": "október", "timeslider.month.november": "november", "timeslider.month.december": "december", - "timeslider.unnamedauthors": "{{num}} névtelen {[plural(num), one: szerző, other: szerzők]}", + "timeslider.unnamedauthors": "{{num}} névtelen {[plural(num), one: szerző, other: szerző]}", "pad.savedrevs.marked": "Ez a revízió mostantól mentettként jelölve", "pad.savedrevs.timeslider": "A mentett revíziókat az időcsúszkán tudod megnézni", "pad.userlist.entername": "Add meg a nevedet", From ed029b599ee83edefd37b14dc44275b24316bf91 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 30 Mar 2017 07:40:12 +0200 Subject: [PATCH 029/102] Localisation updates from https://translatewiki.net. --- src/locales/fr.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/locales/fr.json b/src/locales/fr.json index 47f490c17..8320f6f68 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -22,7 +22,8 @@ "Framafan", "Fylip22", "C13m3n7", - "Wladek92" + "Wladek92", + "Urhixidur" ] }, "index.newPad": "Nouveau pad", @@ -47,7 +48,7 @@ "pad.colorpicker.save": "Enregistrer", "pad.colorpicker.cancel": "Annuler", "pad.loading": "Chargement…", - "pad.noCookie": "Le cookie n’a pas pu être trouvé. Veuillez autoriser les cookies dans votre navigateur !", + "pad.noCookie": "Le témoin (cookie) n’a pas pu être trouvé. Veuillez autoriser les témoins dans votre navigateur !", "pad.passwordRequired": "Vous avez besoin d'un mot de passe pour accéder à ce pad", "pad.permissionDenied": "Vous n'avez pas la permission d’accéder à ce pad", "pad.wrongPassword": "Votre mot de passe est incorrect", From cf6b246688ea8940406ee95c8a146c75e45e4328 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 3 Apr 2017 07:25:13 +0200 Subject: [PATCH 030/102] Localisation updates from https://translatewiki.net. --- src/locales/fr.json | 6 +++--- src/locales/sco.json | 19 ++++++++++++++----- src/locales/tr.json | 3 ++- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/locales/fr.json b/src/locales/fr.json index 8320f6f68..2f4879b96 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -54,7 +54,7 @@ "pad.wrongPassword": "Votre mot de passe est incorrect", "pad.settings.padSettings": "Paramètres du pad", "pad.settings.myView": "Ma vue", - "pad.settings.stickychat": "Toujours afficher le tchat", + "pad.settings.stickychat": "Toujours afficher le clavardage", "pad.settings.chatandusers": "Afficher la discussion et les utilisateurs", "pad.settings.colorcheck": "Couleurs d’identification", "pad.settings.linenocheck": "Numéros de lignes", @@ -103,8 +103,8 @@ "pad.share.readonly": "Lecture seule", "pad.share.link": "Lien", "pad.share.emebdcode": "Incorporer un lien", - "pad.chat": "Chat", - "pad.chat.title": "Ouvrir le chat de ce pad.", + "pad.chat": "Clavardage", + "pad.chat.title": "Ouvrir le clavardoir de ce pad.", "pad.chat.loadmessages": "Charger davantage de messages", "timeslider.pageTitle": "Historique dynamique de {{appTitle}}", "timeslider.toolbar.returnbutton": "Retourner au pad", diff --git a/src/locales/sco.json b/src/locales/sco.json index f7b018244..274a85b48 100644 --- a/src/locales/sco.json +++ b/src/locales/sco.json @@ -1,7 +1,8 @@ { "@metadata": { "authors": [ - "John Reid" + "John Reid", + "AmaryllisGardener" ] }, "index.newPad": "New Pad", @@ -9,14 +10,14 @@ "pad.toolbar.bold.title": "Bold (Ctrl-B)", "pad.toolbar.italic.title": "Italic (Ctrl-I)", "pad.toolbar.underline.title": "Underline (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Cross-oot", - "pad.toolbar.ol.title": "Ordered leet", - "pad.toolbar.ul.title": "Onordered Leet", + "pad.toolbar.strikethrough.title": "Strikethrou (Ctrl+5)", + "pad.toolbar.ol.title": "Ordered leet (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Unordered Leet (Ctrl+Shift+L)", "pad.toolbar.indent.title": "Indent (TAB)", "pad.toolbar.unindent.title": "Ootdent (Shift+TAB)", "pad.toolbar.undo.title": "Ondae (Ctrl-Z)", "pad.toolbar.redo.title": "Redae (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Clear Authorship Colours", + "pad.toolbar.clearAuthorship.title": "Clear Authorship Colours (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Import/Export fae/til different file formats", "pad.toolbar.timeslider.title": "Timeslider", "pad.toolbar.savedRevision.title": "Hain Reveesion", @@ -26,12 +27,14 @@ "pad.colorpicker.save": "Hain", "pad.colorpicker.cancel": "Cancel", "pad.loading": "Laidin...", + "pad.noCookie": "Cookie could nae be foond. Please allae cookies in yer brouser!", "pad.passwordRequired": "Ye need ae passwaird fer tae access this pad", "pad.permissionDenied": "Ye dinna hae permeession tae access this pad", "pad.wrongPassword": "Yer password wis wrang", "pad.settings.padSettings": "Pad Settins", "pad.settings.myView": "Ma Luik", "pad.settings.stickychat": "Tauk aye oan screen", + "pad.settings.chatandusers": "Shaw Chat an Uisers", "pad.settings.colorcheck": "Authorship colours", "pad.settings.linenocheck": "Line nummers", "pad.settings.rtlcheck": "Read content fae richt til cair?", @@ -44,6 +47,7 @@ "pad.importExport.import": "Upload oni tex file or document", "pad.importExport.importSuccessful": "Success!", "pad.importExport.export": "Export current pad as:", + "pad.importExport.exportetherpad": "Etherpad", "pad.importExport.exporthtml": "HTML", "pad.importExport.exportplain": "Plain tex", "pad.importExport.exportword": "Microsoft Word", @@ -89,6 +93,9 @@ "timeslider.exportCurrent": "Export current version as:", "timeslider.version": "Version {{version}}", "timeslider.saved": "Saved {{day}} {{month}}, {{year}}", + "timeslider.playPause": "Playback / Pause Pad Contents", + "timeslider.backRevision": "Gae back a reveesion in this Pad", + "timeslider.forwardRevision": "Gae forwart a reveesion in this Pad", "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", "timeslider.month.january": "Januair", "timeslider.month.february": "Febuair", @@ -104,6 +111,7 @@ "timeslider.month.december": "Dizember", "timeslider.unnamedauthors": "{{num}} onnamed {[plural(num) one: writer, other: writers ]}", "pad.savedrevs.marked": "This reveesion is nou tagged aes ae hained reveesion", + "pad.savedrevs.timeslider": "Ye can see saved reveesions bi veesitin the timeslider", "pad.userlist.entername": "Enter yer name", "pad.userlist.unnamed": "onnamed", "pad.userlist.guest": "Guest", @@ -114,6 +122,7 @@ "pad.impexp.importing": "Importing...", "pad.impexp.confirmimport": "Importin ae file will owerwrite the current tex o the pad. Ar ye sair ye want tae proceed?", "pad.impexp.convertFailed": "We coudna import this file. Please uise ae different document format or copy paste manually", + "pad.impexp.padHasData": "We war nae able tae import this file acause this Pad haes awready haed chynges, please import tae a new pad", "pad.impexp.uploadFailed": "The upload failed, please try again", "pad.impexp.importfailed": "The import failed", "pad.impexp.copypaste": "Please copy paste", diff --git a/src/locales/tr.json b/src/locales/tr.json index bed5c6ece..deb3f58c6 100644 --- a/src/locales/tr.json +++ b/src/locales/tr.json @@ -6,7 +6,8 @@ "Joseph", "Meelo", "Trockya", - "McAang" + "McAang", + "Vito Genovese" ] }, "index.newPad": "Yeni Bloknot", From 9ca56a4c7e2fba7334bab358f2854383134af570 Mon Sep 17 00:00:00 2001 From: jeffreyye <908202572@qq.com> Date: Tue, 4 Apr 2017 15:13:07 +0800 Subject: [PATCH 031/102] wrong path of generate.js --- bin/doc/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/doc/README.md b/bin/doc/README.md index 3646e46e8..4646c2004 100644 --- a/bin/doc/README.md +++ b/bin/doc/README.md @@ -72,5 +72,5 @@ Each type of heading has a description block. Run the following from the etherpad-lite root directory: ```sh -$ node tools/doc/generate doc/index.md --format=html --template=doc/template.html > out.html +$ node bin/doc/generate doc/index.md --format=html --template=doc/template.html > out.html ``` \ No newline at end of file From 009cd3124370d44a9c567332bf3be63826fd95b4 Mon Sep 17 00:00:00 2001 From: Luiza Pagliari Date: Tue, 4 Apr 2017 11:09:24 -0300 Subject: [PATCH 032/102] [feature] Create option to automatically reconnect after a few seconds On some erros that display a modal with "Force reconnect" button, allow Etherpad to automatically reload pad after a few seconds. Amount of seconds is defined on settings.json. Still need to create tests for this feature, and implement i18n. --- settings.json.template | 4 + src/node/handler/PadMessageHandler.js | 9 +- src/node/utils/Settings.js | 5 + src/static/css/pad.css | 17 +++ src/static/js/pad_automatic_reconnect.js | 135 +++++++++++++++++++++++ src/static/js/pad_modals.js | 8 +- src/templates/pad.html | 16 +-- 7 files changed, 180 insertions(+), 14 deletions(-) create mode 100644 src/static/js/pad_automatic_reconnect.js diff --git a/settings.json.template b/settings.json.template index 6af5f78ad..026f5a2bc 100644 --- a/settings.json.template +++ b/settings.json.template @@ -121,6 +121,10 @@ /* Privacy: disable IP logging */ "disableIPlogging" : false, + /* Time (in seconds) to automatically reconnect pad when a "Force reconnect" + message is shown to user. Set to 0 to disable automatic reconnection */ + "automaticReconnectionTimeout" : 0, + /* Users for basic authentication. is_admin = true gives access to /admin. If you do not uncomment this, /admin will not be available! */ /* diff --git a/src/node/handler/PadMessageHandler.js b/src/node/handler/PadMessageHandler.js index 279a44e10..20b262f4e 100644 --- a/src/node/handler/PadMessageHandler.js +++ b/src/node/handler/PadMessageHandler.js @@ -936,7 +936,7 @@ function handleSwitchToPad(client, message) var currentSession = sessioninfos[client.id]; var padId = currentSession.padId; var roomClients = _getRoomClients(padId); - + async.forEach(roomClients, function(client, callback) { var sinfo = sessioninfos[client.id]; if(sinfo && sinfo.author == currentSession.author) { @@ -1115,7 +1115,7 @@ function handleClientReady(client, message) //Check if this author is already on the pad, if yes, kick the other sessions! var roomClients = _getRoomClients(pad.id); - + async.forEach(roomClients, function(client, callback) { var sinfo = sessioninfos[client.id]; if(sinfo && sinfo.author == author) { @@ -1176,6 +1176,7 @@ function handleClientReady(client, message) "accountPrivs": { "maxRevisions": 100 }, + "automaticReconnectionTimeout": settings.automaticReconnectionTimeout, "initialRevisionList": [], "initialOptions": { "guestPolicy": "deny" @@ -1676,13 +1677,13 @@ function composePadChangesets(padId, startNum, endNum, callback) function _getRoomClients(padID) { var roomClients = []; var room = socketio.sockets.adapter.rooms[padID]; - + if (room) { for (var id in room.sockets) { roomClients.push(socketio.sockets.sockets[id]); } } - + return roomClients; } diff --git a/src/node/utils/Settings.js b/src/node/utils/Settings.js index 24bc25c39..a564501dd 100644 --- a/src/node/utils/Settings.js +++ b/src/node/utils/Settings.js @@ -177,6 +177,11 @@ exports.loglevel = "INFO"; */ exports.disableIPlogging = false; +/** + * Number of seconds to automatically reconnect pad + */ +exports.automaticReconnectionTimeout = 0; + /** * Disable Load Testing */ diff --git a/src/static/css/pad.css b/src/static/css/pad.css index 5764c5e4a..0b881d78c 100644 --- a/src/static/css/pad.css +++ b/src/static/css/pad.css @@ -517,6 +517,23 @@ table#otheruserstable { display: block; } +/* styles for the automatic reconnection timer: */ +#connectivity .visible.with_reconnect_timer button, +#connectivity .visible.with_reconnect_timer .reconnecttimer * { + display: inline-block; +} + +#connectivity .with_reconnect_timer .hidden, +#connectivity .with_reconnect_timer #defaulttext.hidden, +#connectivity .with_reconnect_timer button.hidden { + display: none; +} + +#connectivity .with_reconnect_timer #cancelreconnect { + margin-left: 10px; +} +/* end of styles for the automatic reconnection timer */ + #reconnect_form button { font-size: 12pt; padding: 5px; diff --git a/src/static/js/pad_automatic_reconnect.js b/src/static/js/pad_automatic_reconnect.js new file mode 100644 index 000000000..6474838c9 --- /dev/null +++ b/src/static/js/pad_automatic_reconnect.js @@ -0,0 +1,135 @@ + +exports.showCountDownTimerToReconnectOnModal = function($modal) { + if (clientVars.automaticReconnectionTimeout && $modal.is('.with_reconnect_timer')) { + createCountDownElementsIfNecessary($modal); + + var timer = createTimerForModal($modal); + + $modal.find('#cancelreconnect').one('click', function() { + timer.cancel(); + disableAutomaticReconnection($modal); + }); + + enableAutomaticReconnection($modal); + } +} + +var createCountDownElementsIfNecessary = function($modal) { + var elementsDoNotExist = $modal.find('#cancelreconnect').length === 0; + if (elementsDoNotExist) { + var $defaultMessage = $modal.find('#defaulttext'); + var $reconnectButton = $modal.find('#forcereconnect'); + + // create extra DOM elements, if they don't exist + var $reconnectTimerMessage = $('

\ + This window will automatically reconnect in \ + \ +

'); + var $cancelReconnect = $(''); + + $reconnectTimerMessage.insertAfter($defaultMessage); + $cancelReconnect.insertAfter($reconnectButton); + } +} + +var createTimerForModal = function($modal) { + var timer = new CountDownTimer(clientVars.automaticReconnectionTimeout); + + timer.onTick(function(minutes, seconds) { + updateCountDownTimerMessage($modal, minutes, seconds); + }).onExpire(function() { + reconnect($modal); + }).start(); + + return timer; +} + +var disableAutomaticReconnection = function($modal) { + toggleAutomaticReconnectionOption($modal, true); +} +var enableAutomaticReconnection = function($modal) { + toggleAutomaticReconnectionOption($modal, false); +} +var toggleAutomaticReconnectionOption = function($modal, disableAutomaticReconnect) { + $modal.find('#cancelreconnect, .reconnecttimer').toggleClass('hidden', disableAutomaticReconnect); + $modal.find('#defaulttext').toggleClass('hidden', !disableAutomaticReconnect); +} + +var reconnect = function($modal) { + $modal.find('#forcereconnect').click(); +} + +var updateCountDownTimerMessage = function($modal, minutes, seconds) { + minutes = minutes < 10 ? '0' + minutes : minutes; + seconds = seconds < 10 ? '0' + seconds : seconds; + + $modal.find('.timetoexpire').text(minutes + ':' + seconds); +} + +// Timer based on http://stackoverflow.com/a/20618517. +// duration: how many **seconds** until the timer ends +// granularity (optional): how many **milliseconds** between each 'tick' of timer. Default: 1000ms (1s) +var CountDownTimer = function(duration, granularity) { + this.duration = duration; + this.granularity = granularity || 1000; + this.running = false; + + this.onTickCallbacks = []; + this.onExpireCallbacks = []; +} + +CountDownTimer.prototype.start = function() { + if (this.running) { + return; + } + this.running = true; + var start = Date.now(), + that = this, + diff, obj; + + (function timer() { + diff = that.duration - Math.floor((Date.now() - start) / 1000); + + if (diff > 0) { + that.timeoutId = setTimeout(timer, that.granularity); + + obj = CountDownTimer.parse(diff); + that.onTickCallbacks.forEach(function(callback) { + callback.call(this, obj.minutes, obj.seconds); + }, that); + } else { + that.running = false; + + that.onExpireCallbacks.forEach(function(callback) { + callback.call(this); + }, that); + } + }()); +}; + +CountDownTimer.prototype.onTick = function(callback) { + if (typeof callback === 'function') { + this.onTickCallbacks.push(callback); + } + return this; +}; + +CountDownTimer.prototype.onExpire = function(callback) { + if (typeof callback === 'function') { + this.onExpireCallbacks.push(callback); + } + return this; +}; + +CountDownTimer.prototype.cancel = function() { + this.running = false; + clearTimeout(this.timeoutId); + return this; +}; + +CountDownTimer.parse = function(seconds) { + return { + 'minutes': (seconds / 60) | 0, + 'seconds': (seconds % 60) | 0 + }; +}; diff --git a/src/static/js/pad_modals.js b/src/static/js/pad_modals.js index 67b03662f..af0488752 100644 --- a/src/static/js/pad_modals.js +++ b/src/static/js/pad_modals.js @@ -1,5 +1,5 @@ /** - * This code is mostly from the old Etherpad. Please help us to comment this code. + * This code is mostly from the old Etherpad. Please help us to comment this code. * This helps other people to understand this code better and helps them to improve it. * TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED */ @@ -19,8 +19,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + var padeditbar = require('./pad_editbar').padeditbar; +var automaticReconnect = require('./pad_automatic_reconnect'); var padmodals = (function() { @@ -35,6 +36,9 @@ var padmodals = (function() padeditbar.toggleDropDown("none", function() { $("#connectivity .visible").removeClass('visible'); $("#connectivity ."+messageId).addClass('visible'); + + automaticReconnect.showCountDownTimerToReconnectOnModal($('#connectivity .' + messageId)); + padeditbar.toggleDropDown("connectivity"); }); }, diff --git a/src/templates/pad.html b/src/templates/pad.html index 3d89f9d07..7c1f1fb13 100644 --- a/src/templates/pad.html +++ b/src/templates/pad.html @@ -249,12 +249,12 @@

-

+

-

+

@@ -267,16 +267,16 @@

-
+

-

+

-
+

-

+

@@ -288,11 +288,11 @@

-
+
<% e.begin_block("disconnected"); %>

-

+

<% e.end_block(); %>
From 5e907005611caa9ab2b97246f38ad0a086766b80 Mon Sep 17 00:00:00 2001 From: Luiza Pagliari Date: Tue, 4 Apr 2017 13:07:40 -0300 Subject: [PATCH 033/102] [test] Create tests for automatic reconnection on error --- tests/frontend/specs/automatic_reconnect.js | 71 +++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 tests/frontend/specs/automatic_reconnect.js diff --git a/tests/frontend/specs/automatic_reconnect.js b/tests/frontend/specs/automatic_reconnect.js new file mode 100644 index 000000000..e2d2df36a --- /dev/null +++ b/tests/frontend/specs/automatic_reconnect.js @@ -0,0 +1,71 @@ +describe('Automatic pad reload on Force Reconnect message', function() { + var padId, $originalPadFrame; + + beforeEach(function(done) { + padId = helper.newPad(function() { + // enable userdup error to have timer to force reconnect + var $errorMessageModal = helper.padChrome$('#connectivity .userdup'); + $errorMessageModal.addClass('with_reconnect_timer'); + + // make sure there's a timeout set, otherwise automatic reconnect won't be enabled + helper.padChrome$.window.clientVars.automaticReconnectionTimeout = 2; + + // open same pad on another iframe, to force userdup error + var $otherIframeWithSamePad = $(''); + $originalPadFrame = $('#iframe-container iframe'); + $otherIframeWithSamePad.insertAfter($originalPadFrame); + + // wait for modal to be displayed + helper.waitFor(function() { + return $errorMessageModal.is(':visible'); + }, 50000).done(done); + }); + + this.timeout(60000); + }); + + it('displays a count down timer to automatically reconnect', function(done) { + var $errorMessageModal = helper.padChrome$('#connectivity .userdup'); + var $countDownTimer = $errorMessageModal.find('.reconnecttimer'); + + expect($countDownTimer.is(':visible')).to.be(true); + + done(); + }); + + context('and user clicks on Cancel', function() { + beforeEach(function() { + var $errorMessageModal = helper.padChrome$('#connectivity .userdup'); + $errorMessageModal.find('#cancelreconnect').click(); + }); + + it('does not show Cancel button nor timer anymore', function(done) { + var $errorMessageModal = helper.padChrome$('#connectivity .userdup'); + var $countDownTimer = $errorMessageModal.find('.reconnecttimer'); + var $cancelButton = $errorMessageModal.find('#cancelreconnect'); + + expect($countDownTimer.is(':visible')).to.be(false); + expect($cancelButton.is(':visible')).to.be(false); + + done(); + }); + }); + + context('and user does not click on Cancel until timer expires', function() { + var padWasReloaded = false; + + beforeEach(function() { + $originalPadFrame.one('load', function() { + padWasReloaded = true; + }); + }); + + it('reloads the pad', function(done) { + helper.waitFor(function() { + return padWasReloaded; + }, 5000).done(done); + + this.timeout(5000); + }); + }); +}); From 0eae83f2527e2ef963faee5d35993a66e84e26f4 Mon Sep 17 00:00:00 2001 From: Luiza Pagliari Date: Tue, 4 Apr 2017 18:09:33 -0300 Subject: [PATCH 034/102] [feature] i18n for automatic reconnection messages/buttons --- src/locales/en.json | 2 ++ src/static/js/pad_automatic_reconnect.js | 9 ++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/locales/en.json b/src/locales/en.json index 3e16c5de0..2e96880ae 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -74,6 +74,8 @@ "pad.modals.connected": "Connected.", "pad.modals.reconnecting": "Reconnecting to your pad..", "pad.modals.forcereconnect": "Force reconnect", + "pad.modals.reconnecttimer": "This pad will be automatically reconnected in ", + "pad.modals.cancel": "Cancel", "pad.modals.userdup": "Opened in another window", "pad.modals.userdup.explanation": "This pad seems to be opened in more than one browser window on this computer.", diff --git a/src/static/js/pad_automatic_reconnect.js b/src/static/js/pad_automatic_reconnect.js index 6474838c9..3de5ff62c 100644 --- a/src/static/js/pad_automatic_reconnect.js +++ b/src/static/js/pad_automatic_reconnect.js @@ -22,16 +22,23 @@ var createCountDownElementsIfNecessary = function($modal) { // create extra DOM elements, if they don't exist var $reconnectTimerMessage = $('

\ - This window will automatically reconnect in \ + This pad will be automatically reconnected in \ \

'); var $cancelReconnect = $(''); + localize($reconnectTimerMessage); + localize($cancelReconnect); + $reconnectTimerMessage.insertAfter($defaultMessage); $cancelReconnect.insertAfter($reconnectButton); } } +var localize = function($element) { + html10n.translateElement(html10n.translations, $element.get(0)); +}; + var createTimerForModal = function($modal) { var timer = new CountDownTimer(clientVars.automaticReconnectionTimeout); From 384697f65396396c821cbd86d3b3be31d385789c Mon Sep 17 00:00:00 2001 From: Luiza Pagliari Date: Wed, 5 Apr 2017 15:07:37 -0300 Subject: [PATCH 035/102] [feature] Only automatically reconnect if can establish connection to server Avoid trying to reload pad when network is not available. --- src/locales/en.json | 2 +- src/static/js/pad_automatic_reconnect.js | 74 ++++++++++++++++++------ src/static/js/pad_modals.js | 3 +- 3 files changed, 60 insertions(+), 19 deletions(-) diff --git a/src/locales/en.json b/src/locales/en.json index 2e96880ae..9e0d49b3f 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -74,7 +74,7 @@ "pad.modals.connected": "Connected.", "pad.modals.reconnecting": "Reconnecting to your pad..", "pad.modals.forcereconnect": "Force reconnect", - "pad.modals.reconnecttimer": "This pad will be automatically reconnected in ", + "pad.modals.reconnecttimer": "Trying to reconnect in ", "pad.modals.cancel": "Cancel", "pad.modals.userdup": "Opened in another window", diff --git a/src/static/js/pad_automatic_reconnect.js b/src/static/js/pad_automatic_reconnect.js index 3de5ff62c..b5b99bcd0 100644 --- a/src/static/js/pad_automatic_reconnect.js +++ b/src/static/js/pad_automatic_reconnect.js @@ -1,9 +1,9 @@ -exports.showCountDownTimerToReconnectOnModal = function($modal) { +exports.showCountDownTimerToReconnectOnModal = function($modal, pad) { if (clientVars.automaticReconnectionTimeout && $modal.is('.with_reconnect_timer')) { createCountDownElementsIfNecessary($modal); - var timer = createTimerForModal($modal); + var timer = createTimerForModal($modal, pad); $modal.find('#cancelreconnect').one('click', function() { timer.cancel(); @@ -22,7 +22,7 @@ var createCountDownElementsIfNecessary = function($modal) { // create extra DOM elements, if they don't exist var $reconnectTimerMessage = $('

\ - This pad will be automatically reconnected in \ + Trying to reconnect in \ \

'); var $cancelReconnect = $(''); @@ -39,13 +39,20 @@ var localize = function($element) { html10n.translateElement(html10n.translations, $element.get(0)); }; -var createTimerForModal = function($modal) { - var timer = new CountDownTimer(clientVars.automaticReconnectionTimeout); +var createTimerForModal = function($modal, pad) { + var timeUntilReconnection = clientVars.automaticReconnectionTimeout * reconnectionTries.nextTry(); + var timer = new CountDownTimer(timeUntilReconnection); timer.onTick(function(minutes, seconds) { updateCountDownTimerMessage($modal, minutes, seconds); }).onExpire(function() { - reconnect($modal); + var wasANetworkError = $modal.is('.disconnected'); + if (wasANetworkError) { + // cannot simply reconnect, client is having issues to establish connection to server + waitUntilClientCanConnectToServerAndThen(function() { forceReconnection($modal); }, pad); + } else { + forceReconnection($modal); + } }).start(); return timer; @@ -62,7 +69,20 @@ var toggleAutomaticReconnectionOption = function($modal, disableAutomaticReconne $modal.find('#defaulttext').toggleClass('hidden', !disableAutomaticReconnect); } -var reconnect = function($modal) { +var waitUntilClientCanConnectToServerAndThen = function(callback, pad) { + whenConnectionIsRestablishedWithServer(callback, pad); + pad.socket.connect(); +} + +var whenConnectionIsRestablishedWithServer = function(callback, pad) { + // only add listener for the first try, don't need to add another listener + // on every unsuccessful try + if (reconnectionTries.counter === 1) { + pad.socket.once('connect', callback); + } +} + +var forceReconnection = function($modal) { $modal.find('#forcereconnect').click(); } @@ -73,6 +93,20 @@ var updateCountDownTimerMessage = function($modal, minutes, seconds) { $modal.find('.timetoexpire').text(minutes + ':' + seconds); } +// store number of tries to reconnect to server, in order to increase time to wait +// until next try +var reconnectionTries = { + counter: 0, + + nextTry: function() { + // double the time to try to reconnect on every time reconnection fails + var nextCounterFactor = Math.pow(2, this.counter); + this.counter++; + + return nextCounterFactor; + } +} + // Timer based on http://stackoverflow.com/a/20618517. // duration: how many **seconds** until the timer ends // granularity (optional): how many **milliseconds** between each 'tick' of timer. Default: 1000ms (1s) @@ -92,28 +126,34 @@ CountDownTimer.prototype.start = function() { this.running = true; var start = Date.now(), that = this, - diff, obj; + diff; (function timer() { diff = that.duration - Math.floor((Date.now() - start) / 1000); if (diff > 0) { that.timeoutId = setTimeout(timer, that.granularity); - - obj = CountDownTimer.parse(diff); - that.onTickCallbacks.forEach(function(callback) { - callback.call(this, obj.minutes, obj.seconds); - }, that); + that.tick(diff); } else { that.running = false; - - that.onExpireCallbacks.forEach(function(callback) { - callback.call(this); - }, that); + that.tick(0); + that.expire(); } }()); }; +CountDownTimer.prototype.tick = function(diff) { + var obj = CountDownTimer.parse(diff); + this.onTickCallbacks.forEach(function(callback) { + callback.call(this, obj.minutes, obj.seconds); + }, this); +} +CountDownTimer.prototype.expire = function() { + this.onExpireCallbacks.forEach(function(callback) { + callback.call(this); + }, this); +} + CountDownTimer.prototype.onTick = function(callback) { if (typeof callback === 'function') { this.onTickCallbacks.push(callback); diff --git a/src/static/js/pad_modals.js b/src/static/js/pad_modals.js index af0488752..2fc621dc4 100644 --- a/src/static/js/pad_modals.js +++ b/src/static/js/pad_modals.js @@ -37,7 +37,8 @@ var padmodals = (function() $("#connectivity .visible").removeClass('visible'); $("#connectivity ."+messageId).addClass('visible'); - automaticReconnect.showCountDownTimerToReconnectOnModal($('#connectivity .' + messageId)); + var $modal = $('#connectivity .' + messageId); + automaticReconnect.showCountDownTimerToReconnectOnModal($modal, pad); padeditbar.toggleDropDown("connectivity"); }); From eea9304b4d5178257c4107ab903893871d5fd12d Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 6 Apr 2017 07:14:59 +0200 Subject: [PATCH 036/102] Localisation updates from https://translatewiki.net. --- src/locales/sq.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/locales/sq.json b/src/locales/sq.json index d6d959ee6..28485b332 100644 --- a/src/locales/sq.json +++ b/src/locales/sq.json @@ -5,7 +5,7 @@ "Kosovastar" ] }, - "index.newPad": "Bllok i Ri", + "index.newPad": "Bllok i ri", "index.createOpenPad": "ose krijoni/hapni një Bllok me emrin:", "pad.toolbar.bold.title": "Të trasha (Ctrl-B)", "pad.toolbar.italic.title": "Të pjerrëta (Ctrl-I)", @@ -20,7 +20,7 @@ "pad.toolbar.clearAuthorship.title": "Hiqu Ngjyra Autorësish (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Importoni/Eksportoni nga/në formate të tjera kartelash", "pad.toolbar.timeslider.title": "Rrjedha kohore", - "pad.toolbar.savedRevision.title": "Ruaje Rishikimin", + "pad.toolbar.savedRevision.title": "Ruaje rishikimin", "pad.toolbar.settings.title": "Rregullime", "pad.toolbar.embed.title": "Ndajeni me të tjerët dhe Trupëzojeni këtë bllok", "pad.toolbar.showusers.title": "Shfaq përdoruesit në këtë bllok", @@ -88,7 +88,7 @@ "timeslider.pageTitle": "Rrjedhë kohore e {{appTitle}}", "timeslider.toolbar.returnbutton": "Rikthehuni te blloku", "timeslider.toolbar.authors": "Autorë:", - "timeslider.toolbar.authorsList": "S’ka Autorë", + "timeslider.toolbar.authorsList": "S’ka autorë", "timeslider.toolbar.exportlink.title": "Eksportoje", "timeslider.exportCurrent": "Eksportojeni versionin e tanishëm si:", "timeslider.version": "Versioni {{version}}", From db003a1460ab0b8924f5cd4ff47082075e33b309 Mon Sep 17 00:00:00 2001 From: Luiza Pagliari Date: Thu, 6 Apr 2017 03:04:17 -0300 Subject: [PATCH 037/102] [fix] Use new SauceConnect provided by Sauce Labs Could not dowload "Sauce-Connect-latest.zip" anymore, need to change to new version of SauceConnect. --- tests/frontend/travis/sauce_tunnel.sh | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/tests/frontend/travis/sauce_tunnel.sh b/tests/frontend/travis/sauce_tunnel.sh index f519f8d95..1caf01bee 100755 --- a/tests/frontend/travis/sauce_tunnel.sh +++ b/tests/frontend/travis/sauce_tunnel.sh @@ -1,16 +1,14 @@ #!/bin/bash # download and unzip the sauce connector -curl http://saucelabs.com/downloads/Sauce-Connect-latest.zip > /tmp/sauce.zip -unzip /tmp/sauce.zip -d /tmp +curl https://saucelabs.com/downloads/sc-latest-linux.tar.gz > /tmp/sauce.tar.gz +tar zxf /tmp/sauce.tar.gz --directory /tmp +mv sc-*-linux sauce_connect # start the sauce connector in background and make sure it doesn't output the secret key -(java -jar /tmp/Sauce-Connect.jar $SAUCE_USERNAME $SAUCE_ACCESS_KEY -f /tmp/tunnel > /dev/null )& - -# save the sauce pid in a file -echo $! > /tmp/sauce.pid +(/tmp/sauce_connect/bin/sc --user $SAUCE_USERNAME --key $SAUCE_ACCESS_KEY --pidfile /tmp/sauce.pid --readyfile /tmp/tunnel > /dev/null )& # wait for the tunnel to build up while [ ! -e "/tmp/tunnel" ] do - sleep 1 -done \ No newline at end of file + sleep 1 +done From a85eb395b4ee60fa5c0a3dd17128329bb7f20d76 Mon Sep 17 00:00:00 2001 From: Luiza Pagliari Date: Thu, 6 Apr 2017 03:12:45 -0300 Subject: [PATCH 038/102] [fix] Fix path on test script --- tests/frontend/travis/sauce_tunnel.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/frontend/travis/sauce_tunnel.sh b/tests/frontend/travis/sauce_tunnel.sh index 1caf01bee..b19268d05 100755 --- a/tests/frontend/travis/sauce_tunnel.sh +++ b/tests/frontend/travis/sauce_tunnel.sh @@ -2,7 +2,7 @@ # download and unzip the sauce connector curl https://saucelabs.com/downloads/sc-latest-linux.tar.gz > /tmp/sauce.tar.gz tar zxf /tmp/sauce.tar.gz --directory /tmp -mv sc-*-linux sauce_connect +mv /tmp/sc-*-linux /tmp/sauce_connect # start the sauce connector in background and make sure it doesn't output the secret key (/tmp/sauce_connect/bin/sc --user $SAUCE_USERNAME --key $SAUCE_ACCESS_KEY --pidfile /tmp/sauce.pid --readyfile /tmp/tunnel > /dev/null )& From 11813f33a571874567466be9087569a1376ed1ac Mon Sep 17 00:00:00 2001 From: Adam Niederer Date: Sat, 15 Apr 2017 20:12:44 -0400 Subject: [PATCH 039/102] Butt On -> button --- src/templates/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/templates/index.html b/src/templates/index.html index e1f59c1e6..92bea582a 100644 --- a/src/templates/index.html +++ b/src/templates/index.html @@ -161,7 +161,7 @@
<% e.begin_block("indexWrapper"); %>
- +
From 127009f719b2752b0f67c3e34f683a0f7e95500b Mon Sep 17 00:00:00 2001 From: Thomas Wucher Date: Wed, 19 Apr 2017 14:36:48 +0200 Subject: [PATCH 040/102] Use HTTPS for images in README.md This change prevents mixed-content warnings on pages displaying the readme via HTTPS. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d6221250d..7973335c8 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # A really-real time collaborative word processor for the web -![alt text](http://i.imgur.com/zYrGkg3.gif "Etherpad in action on PrimaryPad") +![alt text](https://i.imgur.com/zYrGkg3.gif "Etherpad in action on PrimaryPad") # About Etherpad is a really-real time collaborative editor maintained by the Etherpad Community. From bc5c8ec0cf7ced0c32fc7dd4b0f4fb4663d959f7 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 20 Apr 2017 07:28:20 +0200 Subject: [PATCH 041/102] Localisation updates from https://translatewiki.net. --- src/locales/be-tarask.json | 1 + src/locales/br.json | 2 ++ src/locales/de.json | 2 ++ src/locales/en-gb.json | 5 ++++- src/locales/fr.json | 2 ++ src/locales/hu.json | 5 ++++- src/locales/it.json | 2 ++ src/locales/ko.json | 2 ++ src/locales/lb.json | 1 + src/locales/mk.json | 2 ++ src/locales/qqq.json | 1 + src/locales/zh-hans.json | 2 ++ 12 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/locales/be-tarask.json b/src/locales/be-tarask.json index 2d8c26e85..d70e93858 100644 --- a/src/locales/be-tarask.json +++ b/src/locales/be-tarask.json @@ -58,6 +58,7 @@ "pad.modals.connected": "Падлучыліся.", "pad.modals.reconnecting": "Перападлучэньне да вашага дакумэнта...", "pad.modals.forcereconnect": "Прымусовае перападлучэньне", + "pad.modals.reconnecttimer": "Спрабуем перападключыцца праз", "pad.modals.userdup": "Адкрыта ў іншым акне", "pad.modals.userdup.explanation": "Падобна, дакумэнт адкрыты больш чым у адным акне браўзэра на гэтым кампутары.", "pad.modals.userdup.advice": "Паўторна падключыць з выкарыстаньнем гэтага акна.", diff --git a/src/locales/br.json b/src/locales/br.json index 6a60fa3ae..aa31f7fa0 100644 --- a/src/locales/br.json +++ b/src/locales/br.json @@ -59,6 +59,8 @@ "pad.modals.connected": "Kevreet.", "pad.modals.reconnecting": "Adkevreañ war-zu ho pad...", "pad.modals.forcereconnect": "Adkevreañ dre heg", + "pad.modals.reconnecttimer": "O klask adkevreañ", + "pad.modals.cancel": "Nullañ", "pad.modals.userdup": "Digor en ur prenestr all", "pad.modals.userdup.explanation": "Digor eo ho pad, war a seblant, e meur a brenestr eus ho merdeer en urzhiataer-mañ.", "pad.modals.userdup.advice": "Kevreañ en ur implijout ar prenestr-mañ.", diff --git a/src/locales/de.json b/src/locales/de.json index f32b8cf62..c4ac315ce 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -62,6 +62,8 @@ "pad.modals.connected": "Verbunden.", "pad.modals.reconnecting": "Wiederherstellen der Verbindung …", "pad.modals.forcereconnect": "Erneutes Verbinden erzwingen", + "pad.modals.reconnecttimer": "Versuche Neuverbindung in", + "pad.modals.cancel": "Abbrechen", "pad.modals.userdup": "In einem anderen Fenster geöffnet", "pad.modals.userdup.explanation": "Dieses Pad scheint in mehr als einem Browser-Fenster auf diesem Rechner geöffnet zu sein.", "pad.modals.userdup.advice": "Um stattdessen dieses Fenster zu verwenden, verbinden Sie sich bitte erneut.", diff --git a/src/locales/en-gb.json b/src/locales/en-gb.json index 0cae66e26..c3746f9be 100644 --- a/src/locales/en-gb.json +++ b/src/locales/en-gb.json @@ -2,7 +2,8 @@ "@metadata": { "authors": [ "Chase me ladies, I'm the Cavalry", - "Shirayuki" + "Shirayuki", + "Andibing" ] }, "index.newPad": "New Pad", @@ -57,6 +58,8 @@ "pad.modals.connected": "Connected.", "pad.modals.reconnecting": "Reconnecting to your pad..", "pad.modals.forcereconnect": "Force reconnect", + "pad.modals.reconnecttimer": "Trying to reconnect in", + "pad.modals.cancel": "Cancel", "pad.modals.userdup": "Opened in another window", "pad.modals.userdup.explanation": "This pad seems to be opened in more than one browser window on this computer.", "pad.modals.userdup.advice": "Reconnect to use this window instead.", diff --git a/src/locales/fr.json b/src/locales/fr.json index 2f4879b96..2d311b054 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -78,6 +78,8 @@ "pad.modals.connected": "Connecté.", "pad.modals.reconnecting": "Reconnexion vers votre pad...", "pad.modals.forcereconnect": "Forcer la reconnexion", + "pad.modals.reconnecttimer": "Essai de reconnexion", + "pad.modals.cancel": "Annuler", "pad.modals.userdup": "Ouvert dans une autre fenêtre", "pad.modals.userdup.explanation": "Ce pad semble être ouvert dans plusieurs fenêtres sur cet ordinateur.", "pad.modals.userdup.advice": "Se reconnecter en utilisant cette fenêtre.", diff --git a/src/locales/hu.json b/src/locales/hu.json index 828d92e5d..e8045a7ce 100644 --- a/src/locales/hu.json +++ b/src/locales/hu.json @@ -6,7 +6,8 @@ "R-Joe", "Tgr", "Csega", - "BanKris" + "BanKris", + "Notramo" ] }, "index.newPad": "Új notesz", @@ -61,6 +62,8 @@ "pad.modals.connected": "Kapcsolódva.", "pad.modals.reconnecting": "Újrakapcsolódás a noteszhez...", "pad.modals.forcereconnect": "Újrakapcsolódás kényszerítése", + "pad.modals.reconnecttimer": "Megpróbálok újracsatlakozni ennyi múlva:", + "pad.modals.cancel": "Mégse", "pad.modals.userdup": "Új ablakban megnyitva", "pad.modals.userdup.explanation": "Úgy tűnik, ez a notesz több különböző böngészőablakban is meg van nyitva a számítógépeden.", "pad.modals.userdup.advice": "Kapcsolódj újra, ha ezt az ablakot akarod használni.", diff --git a/src/locales/it.json b/src/locales/it.json index aab7513b2..d28ba9c7b 100644 --- a/src/locales/it.json +++ b/src/locales/it.json @@ -61,6 +61,8 @@ "pad.modals.connected": "Connesso.", "pad.modals.reconnecting": "Riconnessione al pad in corso...", "pad.modals.forcereconnect": "Forza la riconnessione", + "pad.modals.reconnecttimer": "Tentativo di riconnessione", + "pad.modals.cancel": "Annulla", "pad.modals.userdup": "Aperto in un'altra finestra", "pad.modals.userdup.explanation": "Questo Pad sembra essere aperto in più di una finestra del browser su questo computer.", "pad.modals.userdup.advice": "Riconnettiti per utilizzare invece questa finestra.", diff --git a/src/locales/ko.json b/src/locales/ko.json index d0ba7bdcb..0d0a10424 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -61,6 +61,8 @@ "pad.modals.connected": "연결했습니다.", "pad.modals.reconnecting": "패드에 다시 연결 중..", "pad.modals.forcereconnect": "강제로 다시 연결", + "pad.modals.reconnecttimer": "다시 접속 시도 중", + "pad.modals.cancel": "취소", "pad.modals.userdup": "다른 창에서 열리고 있습니다", "pad.modals.userdup.explanation": "이 패드는 이 컴퓨터에 하나보다 많이 브라우저 창에서 열린 것 같습니다.", "pad.modals.userdup.advice": "대신 이 창을 사용해 다시 연결합니다.", diff --git a/src/locales/lb.json b/src/locales/lb.json index 50cebaf2c..2f1432a61 100644 --- a/src/locales/lb.json +++ b/src/locales/lb.json @@ -45,6 +45,7 @@ "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", "pad.modals.connected": "Verbonnen.", + "pad.modals.cancel": "Ofbriechen", "pad.modals.userdup": "An enger anerer Fënster opgemaach", "pad.modals.unauth": "Net autoriséiert", "pad.modals.unauth.explanation": "Är Rechter hu geännert während deem Dir dës säit gekuckt hutt. Probéiert fir Iech nei ze connectéieren.", diff --git a/src/locales/mk.json b/src/locales/mk.json index e292efa60..2ca04171e 100644 --- a/src/locales/mk.json +++ b/src/locales/mk.json @@ -57,6 +57,8 @@ "pad.modals.connected": "Поврзано.", "pad.modals.reconnecting": "Ве преповрзувам со тетратката...", "pad.modals.forcereconnect": "Наметни преповрзување", + "pad.modals.reconnecttimer": "Се преповрзувам за", + "pad.modals.cancel": "Откажи", "pad.modals.userdup": "Отворено во друг прозорец", "pad.modals.userdup.explanation": "Оваа тетратка е отворена на повеќе од еден прозорец (во прелистувач) на сметачот.", "pad.modals.userdup.advice": "Преповрзете се за да го користите овој прозорец.", diff --git a/src/locales/qqq.json b/src/locales/qqq.json index 0beec0cc2..60d62b196 100644 --- a/src/locales/qqq.json +++ b/src/locales/qqq.json @@ -58,6 +58,7 @@ "pad.modals.connected": "Used as HTML

heading to indicate the status.\n\nSee also:\n* {{msg-etherpadlite|Pad.modals.reconnecting}}\n{{Identical|Connected}}", "pad.modals.reconnecting": "Used as HTML

heading to indicate the status.\n\nSee also:\n* {{msg-etherpadlite|Pad.modals.connected}}", "pad.modals.forcereconnect": "Label of a button that will make the browser reconnect to the synchronization server.", + "pad.modals.cancel": "{{Identical|Cancel}}", "pad.modals.userdup": "Used as HTML

heading to indicate that the pad is opened in another window on this computer.\n\nFollowed by the following messages:\n* {{msg-etherpadlite|Pad.modals.userdup.explanation}} -

heading\n* {{msg-etherpadlite|Pad.modals.userdup.advice}}", "pad.modals.userdup.explanation": "Used as HTML

heading.\n\nPreceded by the parent heading {{msg-etherpadlite|Pad.modals.userdup}}.\n\nFollowed by the message {{msg-etherpadlite|Pad.modals.userdup.advice}}.", "pad.modals.userdup.advice": "Preceded by the following headings:\n* {{msg-etherpadlite|Pad.modals.userdup}}\n* {{msg-etherpadlite|Pad.modals.userdup.explanation}}", diff --git a/src/locales/zh-hans.json b/src/locales/zh-hans.json index b4ff306f8..08d33053c 100644 --- a/src/locales/zh-hans.json +++ b/src/locales/zh-hans.json @@ -66,6 +66,8 @@ "pad.modals.connected": "已连接。", "pad.modals.reconnecting": "重新连接到您的记事本...", "pad.modals.forcereconnect": "强制重新连接", + "pad.modals.reconnecttimer": "尝试重新连入", + "pad.modals.cancel": "取消", "pad.modals.userdup": "在另一个窗口中打开", "pad.modals.userdup.explanation": "此记事本似乎在本电脑上的多个浏览器窗口中打开。", "pad.modals.userdup.advice": "重新连接,使用此窗口。", From 5f0e7e01d7a71a8beff8124a07ee3068bba79e2c Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 24 Apr 2017 19:46:41 +0200 Subject: [PATCH 042/102] Localisation updates from https://translatewiki.net. --- src/locales/be-tarask.json | 1 + src/locales/es.json | 5 ++- src/locales/mg.json | 63 ++++++++++++++++++++++++++++++++++++++ src/locales/sr-ec.json | 5 ++- src/locales/zh-hant.json | 2 ++ 5 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 src/locales/mg.json diff --git a/src/locales/be-tarask.json b/src/locales/be-tarask.json index d70e93858..e9421ada2 100644 --- a/src/locales/be-tarask.json +++ b/src/locales/be-tarask.json @@ -59,6 +59,7 @@ "pad.modals.reconnecting": "Перападлучэньне да вашага дакумэнта...", "pad.modals.forcereconnect": "Прымусовае перападлучэньне", "pad.modals.reconnecttimer": "Спрабуем перападключыцца праз", + "pad.modals.cancel": "Адмяніць", "pad.modals.userdup": "Адкрыта ў іншым акне", "pad.modals.userdup.explanation": "Падобна, дакумэнт адкрыты больш чым у адным акне браўзэра на гэтым кампутары.", "pad.modals.userdup.advice": "Паўторна падключыць з выкарыстаньнем гэтага акна.", diff --git a/src/locales/es.json b/src/locales/es.json index b26590630..87683a3e6 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -11,7 +11,8 @@ "Vivaelcelta", "Xuacu", "Macofe", - "Fitoschido" + "Fitoschido", + "Dgstranz" ] }, "index.newPad": "Nuevo pad", @@ -66,6 +67,8 @@ "pad.modals.connected": "Conectado.", "pad.modals.reconnecting": "Reconectando a tu pad..", "pad.modals.forcereconnect": "Forzar reconexión", + "pad.modals.reconnecttimer": "Se intentará reconectar en", + "pad.modals.cancel": "Cancelar", "pad.modals.userdup": "Abierto en otra ventana", "pad.modals.userdup.explanation": "Este pad parece estar abierto en más de una ventana de tu navegador.", "pad.modals.userdup.advice": "Reconectar para usar esta ventana.", diff --git a/src/locales/mg.json b/src/locales/mg.json new file mode 100644 index 000000000..73b954a4b --- /dev/null +++ b/src/locales/mg.json @@ -0,0 +1,63 @@ +{ + "@metadata": { + "authors": [ + "Jagwar" + ] + }, + "index.newPad": "Pad vaovao", + "index.createOpenPad": "na hamorona/hanokatra Pad manana anarana:", + "pad.toolbar.bold.title": "Matevina (Ctrl-B)", + "pad.toolbar.italic.title": "Mandry (Ctrl-L)", + "pad.toolbar.underline.title": "Tsipihana (Ctrl-U)", + "pad.toolbar.strikethrough.title": "Voatsipika", + "pad.toolbar.ol.title": "Lisitra nalamina", + "pad.toolbar.ul.title": "Lisitra tsy voalamina", + "pad.toolbar.undo.title": "Averina (Ctrl-Z)", + "pad.toolbar.redo.title": "Averina (Ctrl-Y)", + "pad.toolbar.clearAuthorship.title": "Hanala ny loko famantarana mpanorona", + "pad.toolbar.import_export.title": "Hampiditra/Hamoaka amin'ny karazan-drakitra hafa", + "pad.colorpicker.save": "Tehirizina", + "pad.colorpicker.cancel": "Aoka ihany", + "pad.loading": "Am-pakàna…", + "pad.settings.myView": "Ny jeriko", + "pad.settings.language": "Fiteny:", + "pad.importExport.import_export": "Hampiditra/Hamoaka", + "pad.importExport.exporthtml": "HTML", + "pad.importExport.exportplain": "Soratra tsotra", + "pad.importExport.exportword": "Microsoft Word", + "pad.importExport.exportpdf": "PDF", + "pad.importExport.exportopen": "ODF (Open Document Format)", + "pad.modals.connected": "Tafaray.", + "pad.modals.cancel": "Aoka ihany", + "pad.modals.unauth": "Tsy nahazo alalana", + "pad.modals.initsocketfail": "Tsy hita ny lohamilina.", + "pad.modals.slowcommit.explanation": "Tsy mamaly ny lohamilina", + "pad.modals.slowcommit.cause": "Izany zavatra izany dia mety nohon'ny fifandraisana ratsy amin'ny lohamilina.", + "pad.modals.badChangeset.explanation": "Voasokajin'ny lohamilim-pirindrana ho tsy azo atao ny fiovana nataonao.", + "pad.modals.badChangeset.cause": "Izany zavatra izany dia mety nohon'ny configuration lohamilina diso na hetsika tsy nampoizina hafa. Mifandraisa amin'ny mpandrindran'ny serivisy, raha heverinao fa hadisoana io. Mifandraisa indray ahafahanao manohy ny fanovana.", + "pad.modals.deleted": "Voafafa.", + "pad.modals.deleted.explanation": "Nesorina ity pad ity.", + "pad.modals.disconnected": "Tapaka ny fifandraisanao.", + "pad.modals.disconnected.explanation": "Very ny fifandraisana tamin'ny lohamilina", + "pad.share.link": "Rohy", + "pad.chat": "Resaka mivantana", + "timeslider.toolbar.authors": "Mpamorona:", + "timeslider.toolbar.authorsList": "Tsy misy mpamorona", + "timeslider.toolbar.exportlink.title": "Avoaka", + "timeslider.exportCurrent": "Hamoaka ny versiona ankehitriny ho:", + "timeslider.version": "Versiona {{version}}", + "timeslider.month.january": "Janoary", + "timeslider.month.february": "Febroary", + "timeslider.month.march": "Martsa", + "timeslider.month.april": "Aprily", + "timeslider.month.may": "Mey", + "timeslider.month.june": "Jiona", + "timeslider.month.july": "Jolay", + "timeslider.month.august": "Aogositra", + "timeslider.month.september": "Septambra", + "timeslider.month.october": "Oktobra", + "timeslider.month.november": "Novambra", + "timeslider.month.december": "Desambra", + "pad.userlist.deny": "Lavina", + "pad.userlist.approve": "Ekena" +} diff --git a/src/locales/sr-ec.json b/src/locales/sr-ec.json index 3d69d52f2..de4137228 100644 --- a/src/locales/sr-ec.json +++ b/src/locales/sr-ec.json @@ -4,7 +4,8 @@ "Aktron", "Milicevic01", "Милан Јелисавчић", - "Srdjan m" + "Srdjan m", + "Obsuser" ] }, "index.newPad": "Нови Пад", @@ -59,6 +60,8 @@ "pad.modals.connected": "Повезано.", "pad.modals.reconnecting": "Поново се повезујем на ваш пад..", "pad.modals.forcereconnect": "Присилно се поново повежи", + "pad.modals.reconnecttimer": "Покушавам се поново повезати", + "pad.modals.cancel": "Откажи", "pad.modals.userdup": "Отворено у другом прозору", "pad.modals.userdup.explanation": "Изгледа да је овај пад отворен у два или више прозора на овом рачунару.", "pad.modals.userdup.advice": "Поново се повежите на овој прозор.", diff --git a/src/locales/zh-hant.json b/src/locales/zh-hant.json index a66ec4161..6977666b5 100644 --- a/src/locales/zh-hant.json +++ b/src/locales/zh-hant.json @@ -63,6 +63,8 @@ "pad.modals.connected": "已連線。", "pad.modals.reconnecting": "重新連接到您的pad...", "pad.modals.forcereconnect": "強制重新連線", + "pad.modals.reconnecttimer": "嘗試重新連接在", + "pad.modals.cancel": "取消", "pad.modals.userdup": "在另一個視窗中開啟", "pad.modals.userdup.explanation": "此pad似乎在此電腦上的多個瀏覽器視窗中開啟。", "pad.modals.userdup.advice": "重新連接到此視窗。", From 51910e91872b05bef916352d8b17838c2f9b2b42 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 27 Apr 2017 08:11:23 +0200 Subject: [PATCH 043/102] Localisation updates from https://translatewiki.net. --- src/locales/ar.json | 4 +++- src/locales/ast.json | 2 ++ src/locales/el.json | 2 ++ src/locales/es.json | 5 +++-- src/locales/gl.json | 2 ++ src/locales/ja.json | 5 ++++- src/locales/lv.json | 1 + 7 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/locales/ar.json b/src/locales/ar.json index 1b9271d1c..914eb9942 100644 --- a/src/locales/ar.json +++ b/src/locales/ar.json @@ -8,7 +8,8 @@ "Test Create account", "محمد أحمد عبد الفتاح", "Haytham morsy", - "ديفيد" + "ديفيد", + "Mido" ] }, "index.newPad": "باد جديد", @@ -63,6 +64,7 @@ "pad.modals.connected": "متصل.", "pad.modals.reconnecting": "إعادة الاتصال ببادك", "pad.modals.forcereconnect": "فرض إعادة الاتصال", + "pad.modals.cancel": "إلغاء", "pad.modals.userdup": "مفتوح في نافذة أخرى", "pad.modals.userdup.explanation": "يبدو أن هذا الباد تم فتحه في أكثر من نافذة متصفح في هذا الحاسوب.", "pad.modals.userdup.advice": "إعادة الاتصال لاستعمال هذه النافذة بدلاً من الأخرى.", diff --git a/src/locales/ast.json b/src/locales/ast.json index e39bf6ef1..f1fd2f5e3 100644 --- a/src/locales/ast.json +++ b/src/locales/ast.json @@ -56,6 +56,8 @@ "pad.modals.connected": "Coneutáu.", "pad.modals.reconnecting": "Reconeutando col to bloc...", "pad.modals.forcereconnect": "Forzar la reconexón", + "pad.modals.reconnecttimer": "Tentando reconeutar en", + "pad.modals.cancel": "Encaboxar", "pad.modals.userdup": "Abiertu n'otra ventana", "pad.modals.userdup.explanation": "Esti bloc paez que ta abiertu en más d'una ventana del navegador d'esti ordenador.", "pad.modals.userdup.advice": "Reconeutar pa usar esta ventana.", diff --git a/src/locales/el.json b/src/locales/el.json index 602b82bdc..2fff2e470 100644 --- a/src/locales/el.json +++ b/src/locales/el.json @@ -60,6 +60,8 @@ "pad.modals.connected": "Συνδεμένοι.", "pad.modals.reconnecting": "Επανασύνδεση στο pad σας...", "pad.modals.forcereconnect": "Επιβολή επανασύνδεσης", + "pad.modals.reconnecttimer": "Επαναπροσπάθεια σε", + "pad.modals.cancel": "Ακύρωση", "pad.modals.userdup": "Ανοιγμένο σε άλλο παράθυρο", "pad.modals.userdup.explanation": "Αυτό το pad φαίνεται να είναι ανοιχτό σε περισσότερα από ένα παράθυρο του προγράμματος περιήγησης σε αυτόν τον υπολογιστή.", "pad.modals.userdup.advice": "Επανασυνδεθείτε για να χρησιμοποιήσετε αυτό το παράθυρο.", diff --git a/src/locales/es.json b/src/locales/es.json index 87683a3e6..68f6d9667 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -12,7 +12,8 @@ "Xuacu", "Macofe", "Fitoschido", - "Dgstranz" + "Dgstranz", + "Luzcaru" ] }, "index.newPad": "Nuevo pad", @@ -67,7 +68,7 @@ "pad.modals.connected": "Conectado.", "pad.modals.reconnecting": "Reconectando a tu pad..", "pad.modals.forcereconnect": "Forzar reconexión", - "pad.modals.reconnecttimer": "Se intentará reconectar en", + "pad.modals.reconnecttimer": "Tratando de reconectar en", "pad.modals.cancel": "Cancelar", "pad.modals.userdup": "Abierto en otra ventana", "pad.modals.userdup.explanation": "Este pad parece estar abierto en más de una ventana de tu navegador.", diff --git a/src/locales/gl.json b/src/locales/gl.json index ff1e9305c..67491763d 100644 --- a/src/locales/gl.json +++ b/src/locales/gl.json @@ -57,6 +57,8 @@ "pad.modals.connected": "Conectado.", "pad.modals.reconnecting": "Reconectando co seu documento...", "pad.modals.forcereconnect": "Forzar a reconexión", + "pad.modals.reconnecttimer": "Intentarase reconectar en", + "pad.modals.cancel": "Cancelar", "pad.modals.userdup": "Aberto noutra ventá", "pad.modals.userdup.explanation": "Semella que este documento está aberto en varias ventás do navegador neste ordenador.", "pad.modals.userdup.advice": "Reconectar para usar esta ventá.", diff --git a/src/locales/ja.json b/src/locales/ja.json index f223a8c44..aeb6ba7d1 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -2,7 +2,8 @@ "@metadata": { "authors": [ "Shirayuki", - "Torinky" + "Torinky", + "Omotecho" ] }, "index.newPad": "新規作成", @@ -57,6 +58,8 @@ "pad.modals.connected": "接続されました。", "pad.modals.reconnecting": "パッドに再接続中...", "pad.modals.forcereconnect": "強制的に再接続", + "pad.modals.reconnecttimer": "再接続を試行中", + "pad.modals.cancel": "中止", "pad.modals.userdup": "別のウィンドウで開かれています", "pad.modals.userdup.explanation": "このコンピューターの複数のブラウザーウィンドウで、このパッドを開いているようです。", "pad.modals.userdup.advice": "代わりにこのウィンドウを再接続します。", diff --git a/src/locales/lv.json b/src/locales/lv.json index b860055a0..7c0bc96cc 100644 --- a/src/locales/lv.json +++ b/src/locales/lv.json @@ -48,6 +48,7 @@ "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open dokumenta formāts)", "pad.modals.connected": "Pievienojies.", + "pad.modals.cancel": "Atcelt", "pad.modals.userdup": "Atvērts citā logā", "pad.modals.unauth": "Nav atļauts", "pad.modals.looping.explanation": "Pastāv sakaru problēmas ar sinhronizācijas servera.", From 32ed4315e2a3c2512d1434c7764391c55d265317 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Tue, 2 May 2017 07:52:46 +0200 Subject: [PATCH 044/102] Localisation updates from https://translatewiki.net. --- src/locales/es.json | 4 ++-- src/locales/he.json | 2 ++ src/locales/sv.json | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/locales/es.json b/src/locales/es.json index 68f6d9667..8053436f7 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -68,7 +68,7 @@ "pad.modals.connected": "Conectado.", "pad.modals.reconnecting": "Reconectando a tu pad..", "pad.modals.forcereconnect": "Forzar reconexión", - "pad.modals.reconnecttimer": "Tratando de reconectar en", + "pad.modals.reconnecttimer": "Se intentará reconectar en", "pad.modals.cancel": "Cancelar", "pad.modals.userdup": "Abierto en otra ventana", "pad.modals.userdup.explanation": "Este pad parece estar abierto en más de una ventana de tu navegador.", @@ -78,7 +78,7 @@ "pad.modals.looping.explanation": "Hay problemas con el servidor de sincronización.", "pad.modals.looping.cause": "Puede deberse a que te conectes a través de un proxy o un cortafuegos incompatible.", "pad.modals.initsocketfail": "Servidor incalcanzable.", - "pad.modals.initsocketfail.explanation": "No se pudo conectar al servidor de sincronización.", + "pad.modals.initsocketfail.explanation": "No se pudo conectar con el servidor de sincronización.", "pad.modals.initsocketfail.cause": "Probablemente debido a un problema en tu navegador o en tu conexión a Internet.", "pad.modals.slowcommit.explanation": "El servidor no responde.", "pad.modals.slowcommit.cause": "Puede deberse a problemas con tu conexión de red.", diff --git a/src/locales/he.json b/src/locales/he.json index 3a6672b24..25dd026eb 100644 --- a/src/locales/he.json +++ b/src/locales/he.json @@ -59,6 +59,8 @@ "pad.modals.connected": "מחובר.", "pad.modals.reconnecting": "מתבצע חיבור מחדש...", "pad.modals.forcereconnect": "לכפות חיבור מחדש", + "pad.modals.reconnecttimer": "מנסה להתחבר מחדש בעוד", + "pad.modals.cancel": "ביטול", "pad.modals.userdup": "פתוח בחלון אחר", "pad.modals.userdup.explanation": "נראה שהפנקס הזה פתוח ביותר מחלון דפדפן אחד במחשב הזה.", "pad.modals.userdup.advice": "להתחבר מחדש באמצעות החלון הזה.", diff --git a/src/locales/sv.json b/src/locales/sv.json index 44df45061..c137f299d 100644 --- a/src/locales/sv.json +++ b/src/locales/sv.json @@ -58,6 +58,8 @@ "pad.modals.connected": "Ansluten.", "pad.modals.reconnecting": "Återansluter till ditt block...", "pad.modals.forcereconnect": "Tvinga återanslutning", + "pad.modals.reconnecttimer": "Försöker ansluta igen", + "pad.modals.cancel": "Avbryt", "pad.modals.userdup": "Öppnades i ett nytt fönster", "pad.modals.userdup.explanation": "Detta block verkar vara öppet i mer än ett fönster på denna dator.", "pad.modals.userdup.advice": "Återanslut för att använda detta fönster istället.", From 0bd41696632f3d15d664253fdf598d6b9746bcff Mon Sep 17 00:00:00 2001 From: Luiza Pagliari Date: Wed, 3 May 2017 12:59:57 -0300 Subject: [PATCH 045/102] [fix] Block user from changing pad after he/she is disconnected Use same approach of when channel state is chaged to "DISCONNECTED". --- src/static/js/pad.js | 44 ++++++++++++--------- tests/frontend/specs/automatic_reconnect.js | 13 ++++++ 2 files changed, 38 insertions(+), 19 deletions(-) diff --git a/src/static/js/pad.js b/src/static/js/pad.js index c967e4615..4fefadf38 100644 --- a/src/static/js/pad.js +++ b/src/static/js/pad.js @@ -1,5 +1,5 @@ /** - * This code is mostly from the old Etherpad. Please help us to comment this code. + * This code is mostly from the old Etherpad. Please help us to comment this code. * This helps other people to understand this code better and helps them to improve it. * TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED */ @@ -99,15 +99,15 @@ function getParams() setting.callback(value); } } - + // Then URL applied stuff var params = getUrlVars() - + for(var i = 0; i < getParameters.length; i++) { var setting = getParameters[i]; var value = params[setting.name]; - + if(value && (value == setting.checkVal || setting.checkVal == null)) { setting.callback(value); @@ -156,7 +156,7 @@ function sendClientReady(isReconnect, messageType) token = "t." + randomString(); createCookie("token", token, 60); } - + var sessionID = decodeURIComponent(readCookie("sessionID")); var password = readCookie("password"); @@ -169,14 +169,14 @@ function sendClientReady(isReconnect, messageType) "token": token, "protocolVersion": 2 }; - + //this is a reconnect, lets tell the server our revisionnumber if(isReconnect == true) { msg.client_rev=pad.collabClient.getCurrentRevisionNumber(); msg.reconnect=true; } - + socket.json.send(msg); } @@ -203,12 +203,12 @@ function handshake() socket.once('connect', function () { sendClientReady(false); }); - + socket.on('reconnect', function () { pad.collabClient.setChannelState("CONNECTED"); pad.sendClientReady(true); }); - + socket.on('reconnecting', function() { pad.collabClient.setChannelState("RECONNECTING"); }); @@ -254,7 +254,7 @@ function handshake() $("#passwordinput").focus(); } } - + //if we haven't recieved the clientVars yet, then this message should it be else if (!receivedClientVars && obj.type == "CLIENT_VARS") { @@ -267,7 +267,7 @@ function handshake() clientVars = obj.data; clientVars.userAgent = "Anonymous"; clientVars.collab_client_vars.clientAgent = "Anonymous"; - + //initalize the pad pad._afterHandshake(); initalized = true; @@ -298,7 +298,7 @@ function handshake() { pad.changeViewOption('noColors', true); } - + if (settings.rtlIsTrue == true) { pad.changeViewOption('rtlIsTrue', true); @@ -335,6 +335,12 @@ function handshake() console.warn(obj); padconnectionstatus.disconnected(obj.disconnect); socket.disconnect(); + + // block user from making any change to the pad + padeditor.disable(); + padeditbar.disable(); + padimpexp.disable(); + return; } else @@ -345,13 +351,13 @@ function handshake() }); // Bind the colorpicker var fb = $('#colorpicker').farbtastic({ callback: '#mycolorpickerpreview', width: 220}); - // Bind the read only button + // Bind the read only button $('#readonlyinput').on('click',function(){ padeditbar.setEmbedLinks(); }); } -$.extend($.gritter.options, { +$.extend($.gritter.options, { position: 'bottom-right', // defaults to 'top-right' but can be 'bottom-left', 'bottom-right', 'top-left', 'top-right' (added in 1.7.1) fade: false, // dont fade, too jerky on mobile time: 6000 // hang on the screen for... @@ -424,7 +430,7 @@ var pad = { if(window.history && window.history.pushState) { $('#chattext p').remove(); //clear the chat messages - window.history.pushState("", "", newHref); + window.history.pushState("", "", newHref); receivedClientVars = false; sendClientReady(false, 'SWITCH_TO_PAD'); } @@ -731,20 +737,20 @@ var pad = { pad.diagnosticInfo.disconnectedMessage = message; pad.diagnosticInfo.padId = pad.getPadId(); pad.diagnosticInfo.socket = {}; - - //we filter non objects from the socket object and put them in the diagnosticInfo + + //we filter non objects from the socket object and put them in the diagnosticInfo //this ensures we have no cyclic data - this allows us to stringify the data for(var i in socket.socket) { var value = socket.socket[i]; var type = typeof value; - + if(type == "string" || type == "number") { pad.diagnosticInfo.socket[i] = value; } } - + pad.asyncSendDiagnosticInfo(); if (typeof window.ajlog == "string") { diff --git a/tests/frontend/specs/automatic_reconnect.js b/tests/frontend/specs/automatic_reconnect.js index e2d2df36a..9e4783e75 100644 --- a/tests/frontend/specs/automatic_reconnect.js +++ b/tests/frontend/specs/automatic_reconnect.js @@ -33,6 +33,19 @@ describe('Automatic pad reload on Force Reconnect message', function() { done(); }); + it('disables editor', function(done) { + var editorDocument = helper.padOuter$("iframe[name='ace_inner']").get(0).contentDocument; + var editorBody = editorDocument.getElementById('innerdocbody'); + + var editorIsEditable = editorBody.contentEditable === 'false' // IE/Safari + || editorDocument.designMode === 'off'; // other browsers + + expect(editorIsEditable).to.be(true); + + done(); + }); + + context('and user clicks on Cancel', function() { beforeEach(function() { var $errorMessageModal = helper.padChrome$('#connectivity .userdup'); From b43137ad2c30b8d8153a7f66ecb493ca3822481f Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 4 May 2017 07:42:20 +0200 Subject: [PATCH 046/102] Localisation updates from https://translatewiki.net. --- src/locales/mg.json | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/locales/mg.json b/src/locales/mg.json index 73b954a4b..5279bdf32 100644 --- a/src/locales/mg.json +++ b/src/locales/mg.json @@ -16,19 +16,34 @@ "pad.toolbar.redo.title": "Averina (Ctrl-Y)", "pad.toolbar.clearAuthorship.title": "Hanala ny loko famantarana mpanorona", "pad.toolbar.import_export.title": "Hampiditra/Hamoaka amin'ny karazan-drakitra hafa", + "pad.toolbar.settings.title": "Fanafahana", "pad.colorpicker.save": "Tehirizina", "pad.colorpicker.cancel": "Aoka ihany", "pad.loading": "Am-pakàna…", + "pad.permissionDenied": "Tsy manana lalalana mijery ity pad ity ianao", + "pad.wrongPassword": "Diso ny tenimiafinao", + "pad.settings.padSettings": "Safidin'ny ped", "pad.settings.myView": "Ny jeriko", + "pad.settings.linenocheck": "Laharan'ny andalana", + "pad.settings.rtlcheck": "Hamaky ny votoatiny miankavia?", + "pad.settings.fontType": "Karazan-tarehintsoratra:", + "pad.settings.globalView": "Jery ankapobe", "pad.settings.language": "Fiteny:", "pad.importExport.import_export": "Hampiditra/Hamoaka", + "pad.importExport.import": "Hampiditra raki-tsoratra na rakitra", + "pad.importExport.importSuccessful": "Vita soa aman-tsara!", + "pad.importExport.export": "Hamoaka ny pad ankehitriny ho:", + "pad.importExport.exportetherpad": "Etherpad", "pad.importExport.exporthtml": "HTML", "pad.importExport.exportplain": "Soratra tsotra", "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", "pad.modals.connected": "Tafaray.", + "pad.modals.forcereconnect": "Hanery ny famerenam-pifandraisana", + "pad.modals.reconnecttimer": "Manandrana mamerim-pifandraisana", "pad.modals.cancel": "Aoka ihany", + "pad.modals.userdup": "Nosokafana tanaty varavarankely hafa", "pad.modals.unauth": "Tsy nahazo alalana", "pad.modals.initsocketfail": "Tsy hita ny lohamilina.", "pad.modals.slowcommit.explanation": "Tsy mamaly ny lohamilina", @@ -39,13 +54,21 @@ "pad.modals.deleted.explanation": "Nesorina ity pad ity.", "pad.modals.disconnected": "Tapaka ny fifandraisanao.", "pad.modals.disconnected.explanation": "Very ny fifandraisana tamin'ny lohamilina", + "pad.share": "Hizara ity pad ity", + "pad.share.readonly": "Vakiana ihany", "pad.share.link": "Rohy", + "pad.share.emebdcode": "Hampiditra URL", "pad.chat": "Resaka mivantana", + "pad.chat.title": "Hampiditra ny karajia ho an'ity pad ity.", + "pad.chat.loadmessages": "Haka hafatra be kokoa", + "timeslider.pageTitle": "Tantara dinamikan'i {{appTitle}}", + "timeslider.toolbar.returnbutton": "Hiverina amin'ny pad", "timeslider.toolbar.authors": "Mpamorona:", "timeslider.toolbar.authorsList": "Tsy misy mpamorona", "timeslider.toolbar.exportlink.title": "Avoaka", "timeslider.exportCurrent": "Hamoaka ny versiona ankehitriny ho:", "timeslider.version": "Versiona {{version}}", + "timeslider.saved": "Notahirizina ny {{day}} {{month}} {{year}}", "timeslider.month.january": "Janoary", "timeslider.month.february": "Febroary", "timeslider.month.march": "Martsa", @@ -58,6 +81,10 @@ "timeslider.month.october": "Oktobra", "timeslider.month.november": "Novambra", "timeslider.month.december": "Desambra", + "pad.userlist.unnamed": "tsy manana naarana", + "pad.userlist.guest": "Nasaina", "pad.userlist.deny": "Lavina", - "pad.userlist.approve": "Ekena" + "pad.userlist.approve": "Ekena", + "pad.impexp.importbutton": "Ampidirina izao", + "pad.impexp.importing": "Mampiditra..." } From 4eec3763b4110cbd7b436a0c6505055ee5ca2af5 Mon Sep 17 00:00:00 2001 From: Luiza Pagliari Date: Thu, 4 May 2017 11:22:18 -0300 Subject: [PATCH 047/102] [fix] Close modals when user clicks both on pad inner and outer Also: split tests for automatic reconnection and regular modal tests. --- src/static/js/ace2_inner.js | 9 ++- tests/frontend/specs/automatic_reconnect.js | 13 ----- tests/frontend/specs/pad_modal.js | 64 +++++++++++++++++++++ 3 files changed, 72 insertions(+), 14 deletions(-) create mode 100644 tests/frontend/specs/pad_modal.js diff --git a/src/static/js/ace2_inner.js b/src/static/js/ace2_inner.js index f44a6583a..b1aebf3cf 100644 --- a/src/static/js/ace2_inner.js +++ b/src/static/js/ace2_inner.js @@ -3367,7 +3367,12 @@ function Ace2Inner(){ evt.preventDefault(); } } - //hide the dropdownso + + hideEditBarDropdowns(); + } + + function hideEditBarDropdowns() + { if(window.parent.parent.padeditbar){ // required in case its in an iframe should probably use parent.. See Issue 327 https://github.com/ether/etherpad-lite/issues/327 window.parent.parent.padeditbar.toggleDropDown("none"); } @@ -4983,6 +4988,8 @@ function Ace2Inner(){ $(document).on("keypress", handleKeyEvent); $(document).on("keyup", handleKeyEvent); $(document).on("click", handleClick); + // dropdowns on edit bar need to be closed on clicks on both pad inner and pad outer + $(outerWin.document).on("click", hideEditBarDropdowns); // Disabled: https://github.com/ether/etherpad-lite/issues/2546 // Will break OL re-numbering: https://github.com/ether/etherpad-lite/pull/2533 // $(document).on("cut", handleCut); diff --git a/tests/frontend/specs/automatic_reconnect.js b/tests/frontend/specs/automatic_reconnect.js index 9e4783e75..e2d2df36a 100644 --- a/tests/frontend/specs/automatic_reconnect.js +++ b/tests/frontend/specs/automatic_reconnect.js @@ -33,19 +33,6 @@ describe('Automatic pad reload on Force Reconnect message', function() { done(); }); - it('disables editor', function(done) { - var editorDocument = helper.padOuter$("iframe[name='ace_inner']").get(0).contentDocument; - var editorBody = editorDocument.getElementById('innerdocbody'); - - var editorIsEditable = editorBody.contentEditable === 'false' // IE/Safari - || editorDocument.designMode === 'off'; // other browsers - - expect(editorIsEditable).to.be(true); - - done(); - }); - - context('and user clicks on Cancel', function() { beforeEach(function() { var $errorMessageModal = helper.padChrome$('#connectivity .userdup'); diff --git a/tests/frontend/specs/pad_modal.js b/tests/frontend/specs/pad_modal.js new file mode 100644 index 000000000..d3afe107e --- /dev/null +++ b/tests/frontend/specs/pad_modal.js @@ -0,0 +1,64 @@ +describe('Pad modal', function() { + var padId, $originalPadFrame; + + beforeEach(function(done) { + padId = helper.newPad(function() { + // open same pad on another iframe, to force userdup error + var $otherIframeWithSamePad = $(''); + $originalPadFrame = $('#iframe-container iframe'); + $otherIframeWithSamePad.insertAfter($originalPadFrame); + + // wait for modal to be displayed + var $errorMessageModal = helper.padChrome$('#connectivity .userdup'); + helper.waitFor(function() { + return $errorMessageModal.is(':visible'); + }, 50000).done(done); + }); + + this.timeout(60000); + }); + + it('disables editor', function(done) { + var editorDocument = helper.padOuter$("iframe[name='ace_inner']").get(0).contentDocument; + var editorBody = editorDocument.getElementById('innerdocbody'); + + var editorIsEditable = editorBody.contentEditable === 'false' // IE/Safari + || editorDocument.designMode === 'off'; // other browsers + + expect(editorIsEditable).to.be(true); + + done(); + }); + + context('and user clicks on editor', function() { + beforeEach(function() { + var $editor = helper.padInner$('#innerdocbody'); + $editor.click(); + }); + + it('closes the modal', function(done) { + var $errorMessageModal = helper.padChrome$('#connectivity .userdup'); + var modalIsVisible = $errorMessageModal.is(':visible'); + + expect(modalIsVisible).to.be(false); + + done(); + }); + }); + + context('and user clicks on pad outer', function() { + beforeEach(function() { + var $lineNumbersColumn = helper.padOuter$('#sidedivinner'); + $lineNumbersColumn.click(); + }); + + it('closes the modal', function(done) { + var $errorMessageModal = helper.padChrome$('#connectivity .userdup'); + var modalIsVisible = $errorMessageModal.is(':visible'); + + expect(modalIsVisible).to.be(false); + + done(); + }); + }); +}); From 9176bf9bad8d30828ec7cf215357d5a054842c57 Mon Sep 17 00:00:00 2001 From: Luiza Pagliari Date: Thu, 4 May 2017 14:34:01 -0300 Subject: [PATCH 048/102] [fix] Do not close "force reconnect" messages If a "force reconnect" message is displayed to the user, it means the only way to go back to a healthy state is to reload the pad. So we cannot hide this kind of message, like what is done with other modals (eg: "settings"). --- src/static/js/pad_editbar.js | 24 +++-- tests/frontend/specs/pad_modal.js | 171 +++++++++++++++++++++--------- 2 files changed, 137 insertions(+), 58 deletions(-) diff --git a/src/static/js/pad_editbar.js b/src/static/js/pad_editbar.js index dd1c377a3..b2aade466 100644 --- a/src/static/js/pad_editbar.js +++ b/src/static/js/pad_editbar.js @@ -259,18 +259,25 @@ var padeditbar = (function() // hide all modules and remove highlighting of all buttons if(moduleName == "none") { - var returned = false + var returned = false; for(var i=0;i a").removeClass("selected"); + $("li[data-key=" + thisModuleName + "] > a").removeClass("selected"); module.slideUp("fast", cb); returned = true; } @@ -283,16 +290,17 @@ var padeditbar = (function() // respectively add highlighting to the corresponding button for(var i=0;i a").removeClass("selected"); + $("li[data-key=" + thisModuleName + "] > a").removeClass("selected"); module.slideUp("fast"); } - else if(self.dropdowns[i]==moduleName) + else if(thisModuleName==moduleName) { - $("li[data-key=" + self.dropdowns[i] + "] > a").addClass("selected"); + $("li[data-key=" + thisModuleName + "] > a").addClass("selected"); module.slideDown("fast", cb); } } diff --git a/tests/frontend/specs/pad_modal.js b/tests/frontend/specs/pad_modal.js index d3afe107e..15eb8ac86 100644 --- a/tests/frontend/specs/pad_modal.js +++ b/tests/frontend/specs/pad_modal.js @@ -1,64 +1,135 @@ describe('Pad modal', function() { - var padId, $originalPadFrame; + context('when modal is a "force reconnect" message', function() { + var MODAL_SELECTOR = '#connectivity .userdup'; - beforeEach(function(done) { - padId = helper.newPad(function() { - // open same pad on another iframe, to force userdup error - var $otherIframeWithSamePad = $(''); - $originalPadFrame = $('#iframe-container iframe'); - $otherIframeWithSamePad.insertAfter($originalPadFrame); + var padId, $originalPadFrame; - // wait for modal to be displayed - var $errorMessageModal = helper.padChrome$('#connectivity .userdup'); - helper.waitFor(function() { - return $errorMessageModal.is(':visible'); - }, 50000).done(done); + beforeEach(function(done) { + padId = helper.newPad(function() { + // open same pad on another iframe, to force userdup error + var $otherIframeWithSamePad = $(''); + $originalPadFrame = $('#iframe-container iframe'); + $otherIframeWithSamePad.insertAfter($originalPadFrame); + + // wait for modal to be displayed + var $modal = helper.padChrome$(MODAL_SELECTOR); + helper.waitFor(function() { + return $modal.is(':visible'); + }, 50000).done(done); + }); + + this.timeout(60000); }); - this.timeout(60000); + it('disables editor', function(done) { + expect(isEditorDisabled()).to.be(true); + + done(); + }); + + context('and user clicks on editor', function() { + beforeEach(function() { + clickOnPadInner(); + }); + + it('does not close the modal', function(done) { + var $modal = helper.padChrome$(MODAL_SELECTOR); + var modalIsVisible = $modal.is(':visible'); + + expect(modalIsVisible).to.be(true); + + done(); + }); + }); + + context('and user clicks on pad outer', function() { + beforeEach(function() { + clickOnPadOuter(); + }); + + it('does not close the modal', function(done) { + var $modal = helper.padChrome$(MODAL_SELECTOR); + var modalIsVisible = $modal.is(':visible'); + + expect(modalIsVisible).to.be(true); + + done(); + }); + }); }); - it('disables editor', function(done) { + // we use "settings" here, but other modals have the same behaviour + context('when modal is not an error message', function() { + var MODAL_SELECTOR = '#settings'; + + beforeEach(function(done) { + helper.newPad(function() { + openSettingsAndWaitForModalToBeVisible(done); + }); + + this.timeout(60000); + }); + + it('does not disable editor', function(done) { + expect(isEditorDisabled()).to.be(false); + done(); + }); + + context('and user clicks on editor', function() { + beforeEach(function() { + clickOnPadInner(); + }); + + it('closes the modal', function(done) { + expect(isModalOpened(MODAL_SELECTOR)).to.be(false); + done(); + }); + }); + + context('and user clicks on pad outer', function() { + beforeEach(function() { + clickOnPadOuter(); + }); + + it('closes the modal', function(done) { + expect(isModalOpened(MODAL_SELECTOR)).to.be(false); + done(); + }); + }); + }); + + var clickOnPadInner = function() { + var $editor = helper.padInner$('#innerdocbody'); + $editor.click(); + } + + var clickOnPadOuter = function() { + var $lineNumbersColumn = helper.padOuter$('#sidedivinner'); + $lineNumbersColumn.click(); + } + + var openSettingsAndWaitForModalToBeVisible = function(done) { + helper.padChrome$('.buttonicon-settings').click(); + + // wait for modal to be displayed + var modalSelector = '#settings'; + helper.waitFor(function() { + return isModalOpened(modalSelector); + }, 10000).done(done); + } + + var isEditorDisabled = function() { var editorDocument = helper.padOuter$("iframe[name='ace_inner']").get(0).contentDocument; var editorBody = editorDocument.getElementById('innerdocbody'); - var editorIsEditable = editorBody.contentEditable === 'false' // IE/Safari + var editorIsDisabled = editorBody.contentEditable === 'false' // IE/Safari || editorDocument.designMode === 'off'; // other browsers - expect(editorIsEditable).to.be(true); + return editorIsDisabled; + } - done(); - }); - - context('and user clicks on editor', function() { - beforeEach(function() { - var $editor = helper.padInner$('#innerdocbody'); - $editor.click(); - }); - - it('closes the modal', function(done) { - var $errorMessageModal = helper.padChrome$('#connectivity .userdup'); - var modalIsVisible = $errorMessageModal.is(':visible'); - - expect(modalIsVisible).to.be(false); - - done(); - }); - }); - - context('and user clicks on pad outer', function() { - beforeEach(function() { - var $lineNumbersColumn = helper.padOuter$('#sidedivinner'); - $lineNumbersColumn.click(); - }); - - it('closes the modal', function(done) { - var $errorMessageModal = helper.padChrome$('#connectivity .userdup'); - var modalIsVisible = $errorMessageModal.is(':visible'); - - expect(modalIsVisible).to.be(false); - - done(); - }); - }); + var isModalOpened = function(modalSelector) { + var $modal = helper.padChrome$(modalSelector); + return $modal.is(':visible'); + } }); From 96cc1ad55acd077f7e3ecc18685b7cee0cb58e18 Mon Sep 17 00:00:00 2001 From: Mikk Andresen Date: Fri, 5 May 2017 10:28:44 +0300 Subject: [PATCH 049/102] Use different cookie name for different protocols - https://github.com/ether/etherpad-lite/issues/3179 --- src/static/js/pad_cookie.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/static/js/pad_cookie.js b/src/static/js/pad_cookie.js index b563a7e60..72eb3fe95 100644 --- a/src/static/js/pad_cookie.js +++ b/src/static/js/pad_cookie.js @@ -23,6 +23,8 @@ var padcookie = (function() { + var cookieName = isHttpsScheme() ? "prefs" : "prefsHttp"; + function getRawCookie() { // returns null if can't get cookie text @@ -31,7 +33,7 @@ var padcookie = (function() return null; } // look for (start of string OR semicolon) followed by whitespace followed by prefs=(something); - var regexResult = document.cookie.match(/(?:^|;)\s*prefs=([^;]*)(?:;|$)/); + var regexResult = document.cookie.match(new RegExp("(?:^|;)\s*" + cookieName + "=([^;]*)(?:;|$)")); if ((!regexResult) || (!regexResult[1])) { return null; @@ -44,7 +46,7 @@ var padcookie = (function() var expiresDate = new Date(); expiresDate.setFullYear(3000); var secure = isHttpsScheme() ? ";secure" : ""; - document.cookie = ('prefs=' + safeText + ';expires=' + expiresDate.toGMTString() + secure); + document.cookie = (cookieName + "=" + safeText + ";expires=" + expiresDate.toGMTString() + secure); } function parseCookie(text) From 7790c5606bfb6fefb11aab8b00f2d7caecfa127a Mon Sep 17 00:00:00 2001 From: Mikk Andresen Date: Fri, 5 May 2017 10:54:26 +0300 Subject: [PATCH 050/102] Fix regexp --- src/static/js/pad_cookie.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/static/js/pad_cookie.js b/src/static/js/pad_cookie.js index 72eb3fe95..f6ef1aa40 100644 --- a/src/static/js/pad_cookie.js +++ b/src/static/js/pad_cookie.js @@ -33,7 +33,7 @@ var padcookie = (function() return null; } // look for (start of string OR semicolon) followed by whitespace followed by prefs=(something); - var regexResult = document.cookie.match(new RegExp("(?:^|;)\s*" + cookieName + "=([^;]*)(?:;|$)")); + var regexResult = document.cookie.match(new RegExp("(?:^|;)\\s*" + cookieName + "=([^;]*)(?:;|$)")); if ((!regexResult) || (!regexResult[1])) { return null; From 582e2c3819bbecb41bad55b5a66ceb7b3bc3aaac Mon Sep 17 00:00:00 2001 From: Mikk Andresen Date: Fri, 5 May 2017 11:07:54 +0300 Subject: [PATCH 051/102] Use padcookie instead of raw prefs cookie reading --- src/static/js/pad.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/static/js/pad.js b/src/static/js/pad.js index c967e4615..0c825eeb8 100644 --- a/src/static/js/pad.js +++ b/src/static/js/pad.js @@ -453,7 +453,7 @@ var pad = { // This will check if the prefs-cookie is set. // Otherwise it shows up a message to the user. padcookie.init(); - if (!readCookie("prefs")) + if (padcookie.wasNoCookie()) { $('#loading').hide(); $('#noCookie').show(); From c959cdbaa7a59ffe594710b2c86c369d55817385 Mon Sep 17 00:00:00 2001 From: Mikk Andresen Date: Fri, 5 May 2017 11:17:07 +0300 Subject: [PATCH 052/102] Pad_cookie.js to have isCookiesEnabled() cause wasNoCookie() is also true when User visits first time. --- src/static/js/pad.js | 2 +- src/static/js/pad_cookie.js | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/static/js/pad.js b/src/static/js/pad.js index 0c825eeb8..9c3de091e 100644 --- a/src/static/js/pad.js +++ b/src/static/js/pad.js @@ -453,7 +453,7 @@ var pad = { // This will check if the prefs-cookie is set. // Otherwise it shows up a message to the user. padcookie.init(); - if (padcookie.wasNoCookie()) + if (!padcookie.isCookiesEnabled()) { $('#loading').hide(); $('#noCookie').show(); diff --git a/src/static/js/pad_cookie.js b/src/static/js/pad_cookie.js index f6ef1aa40..62c88cffe 100644 --- a/src/static/js/pad_cookie.js +++ b/src/static/js/pad_cookie.js @@ -124,6 +124,9 @@ var padcookie = (function() { return wasNoCookie; }, + isCookiesEnabled: function() { + return !!getRawCookie(); + }, getPref: function(prefName) { return cookieData[prefName]; From 2dc3eb79d2f2de0fbbcbde54686155fa93819a38 Mon Sep 17 00:00:00 2001 From: Alexey Pyltsyn Date: Tue, 9 May 2017 08:28:29 +0300 Subject: [PATCH 053/102] Fix links to README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7973335c8..de1f36199 100644 --- a/README.md +++ b/README.md @@ -117,9 +117,9 @@ Join the [mailinglist](http://groups.google.com/group/etherpad-lite-dev) and mak * [async-stacktrace](https://github.com/Pita/async-stacktrace) "Improves node.js stacktraces and makes it easier to handle errors" # Donate! -* [Flattr] (http://flattr.com/thing/71378/Etherpad-Foundation) +* [Flattr](http://flattr.com/thing/71378/Etherpad-Foundation) * Paypal - Press the donate button on [etherpad.org](http://etherpad.org) -* [Bitcoin] (https://coinbase.com/checkouts/1e572bf8a82e4663499f7f1f66c2d15a) +* [Bitcoin](https://coinbase.com/checkouts/1e572bf8a82e4663499f7f1f66c2d15a) # License [Apache License v2](http://www.apache.org/licenses/LICENSE-2.0.html) From ef415880f0e42a670897410af50b186934098d04 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 11 May 2017 08:32:44 +0200 Subject: [PATCH 054/102] Localisation updates from https://translatewiki.net. --- src/locales/dty.json | 62 +++++++++++++++++++++++--------------------- src/locales/nb.json | 5 +++- src/locales/ru.json | 1 + 3 files changed, 37 insertions(+), 31 deletions(-) diff --git a/src/locales/dty.json b/src/locales/dty.json index c0d439e6a..0682da67a 100644 --- a/src/locales/dty.json +++ b/src/locales/dty.json @@ -6,8 +6,8 @@ "Nirajan pant" ] }, - "index.newPad": "नयाँ प्याड", - "index.createOpenPad": "नाम सहितको नयाँ प्याड सिर्जना गद्य्या / खोल्या :", + "index.newPad": "नौलो प्याड", + "index.createOpenPad": "नाउँ सहितको नौलो प्याड सिर्जना गद्य्या / खोल्ल्या :", "pad.toolbar.bold.title": "मोटो (Ctrl-B)", "pad.toolbar.italic.title": "ढल्के (Ctrl-I)", "pad.toolbar.underline.title": "इसो रेखाङ्कन (Ctrl-U)", @@ -16,46 +16,48 @@ "pad.toolbar.ul.title": "अक्रमाङ्कित सूची (Ctrl+Shift+L)", "pad.toolbar.indent.title": "इन्डेन्ट (TAB)", "pad.toolbar.unindent.title": "आउटडेन्ट (Shift+TAB)", - "pad.toolbar.undo.title": "खारेजी (Ctrl-Z)", + "pad.toolbar.undo.title": "अण्डू (Ctrl-Z)", "pad.toolbar.redo.title": "दोसर्या:लागु (Ctrl-Y)", "pad.toolbar.clearAuthorship.title": "लेखकीय रङ्ग हटाउन्या (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "विविध फाइल फर्म्याटअन बठेइ/मी आयात/निर्यात", "pad.toolbar.timeslider.title": "टाइमस्लाइडर", - "pad.toolbar.savedRevision.title": "पुनरावलोकन संग्रहा गद्य्य", - "pad.toolbar.settings.title": "सेटिङ्गहरू", + "pad.toolbar.savedRevision.title": "पुनरावलोकन संग्रह गद्य्या", + "pad.toolbar.settings.title": "सेटिङ्गअन", "pad.toolbar.embed.title": "यै प्याडलाई बाड्न्या यात इम्बेड गद्य्या", "pad.toolbar.showusers.title": "यै प्याडमि रयाका प्रयोगकर्ता देखाउन्या", "pad.colorpicker.save": "सङ्ग्रह गद्या", "pad.colorpicker.cancel": "खारेजी", - "pad.loading": "लोड हुन्नाछ....", + "pad.loading": "लोड हुन्नाछ़....", "pad.noCookie": "कुकी पाउन नाइ सकियो। तमरा ब्राउजरमी कुकी राख्दाइ अनुमति दिय!", - "pad.passwordRequired": "यो प्यड खोल्लाकी पासवर्ड चाहिन्छ", + "pad.passwordRequired": "यो प्याड खोल्लाकी पासवर्ड चाहिन्छ", "pad.permissionDenied": "तमलाईँ यै प्याड खोल्लाकी अनुमति नाइथिन", "pad.wrongPassword": "तमरो पासवर्ड गलत थ्यो", - "pad.settings.padSettings": "प्याड सेटिङ्गहरू", + "pad.settings.padSettings": "प्याड सेटिङ्गअन", "pad.settings.myView": "मेरि हेराइ", - "pad.settings.stickychat": "पर्दामा जबलई कुरडी गद्य्या", - "pad.settings.chatandusers": "वार्ता और प्रयोगकर्ताहरू देखाउन्या", + "pad.settings.stickychat": "जबलई पर्दामी कुरडी गद्य्या", + "pad.settings.chatandusers": "वार्ता और प्रयोगकर्ताअन देखाउन्या", "pad.settings.colorcheck": "लेखकीय रङ्ग", "pad.settings.linenocheck": "हरफ संख्या", - "pad.settings.rtlcheck": "के सामग्री दाहिना बठे देब्रे पढ्न्या हो ?", + "pad.settings.rtlcheck": "सामग्री दाहिना बठे देब्रे पढ्न्या हो कि?", "pad.settings.fontType": "फन्ट प्रकार:", "pad.settings.globalView": "विश्वव्यापी दृष्य", - "pad.settings.language": "भाषा: $1", - "pad.importExport.import_export": "आउन्या/झान्या", - "pad.importExport.import": "कोइलै पाठ रयाको फाइल और कागजात अपलोड गरिदिय", + "pad.settings.language": "भाषा:", + "pad.importExport.import_export": "आयात/निर्यात", + "pad.importExport.import": "कोइलै पाठ फाइल और कागजात अपलोड अरऽ", "pad.importExport.importSuccessful": "सफल भयो!", - "pad.importExport.export": "निम्न रुपमि प्याड पठौन्या :", + "pad.importExport.export": "निम्न रुपमि प्याड निर्यात:", "pad.importExport.exportetherpad": "इथरप्याड", - "pad.importExport.exporthtml": "हटमेल", - "pad.importExport.exportplain": "सानतिनो पाठ", + "pad.importExport.exporthtml": "HTML", + "pad.importExport.exportplain": "सादा पाठ", "pad.importExport.exportword": "माइक्रोसफ्ट वर्ड", "pad.importExport.exportpdf": "पिडिएफ", - "pad.importExport.exportopen": "ओडिएफ(खुल्ला कागजात ढाँचा)", + "pad.importExport.exportopen": "ओडिएफ (खुल्ला कागजात ढाँचा)", "pad.importExport.abiword.innerHTML": "तम सादा पाठ या HTML ढाँचा बठेइ मात्तरी आयात अरीसकन्छऽ। विस्तारित आयात विशेषता खिलाई कृपया abiword स्थापना अरऽ।", - "pad.modals.connected": "जोडीयाको", - "pad.modals.reconnecting": "तमरो प्याडमि आजि: जडान हुन्नाछ", + "pad.modals.connected": "जोडीयाको।", + "pad.modals.reconnecting": "तमरा प्याडमि दोबरा जडान अद्‍दाछ़..", "pad.modals.forcereconnect": "बलात् पुन:जडान", + "pad.modals.reconnecttimer": "दोबरा जोड्‍डाइ प्रयास अद्‍दाछ़", + "pad.modals.cancel": "रद्द", "pad.modals.userdup": "अर्खा विण्डोमी खुलिरैछ", "pad.modals.userdup.explanation": "यो प्याड येइ कम्प्युटरमी एक़ है बर्ता ब्राउजर सञ्झ्यालमी खोल्याऽ धेकीँछ।", "pad.modals.userdup.advice": "बरु यो विण्डो प्रयोग अद्दाइ दोसर्‍याँ जोणिय।", @@ -63,8 +65,8 @@ "pad.modals.unauth.explanation": "येइ पन्ना हेरनज्याँ तमरा अधिकार बदेलिया। दोसर्‍याँ जोणिन्या प्रयास अरऽ।", "pad.modals.looping.explanation": "सिक्रोनाइजेसन सर्भर सित सञ्चार समस्या धेकिन्नाछ़।", "pad.modals.looping.cause": "शायद तम यक असंगत फायरवाल या प्रोक्सी का माध्यम बठेइ जोणीरैछऽ।", - "pad.modals.initsocketfail": "सर्भरमा पहुँच पुर्‍याउन नाइसकियो ।", - "pad.modals.initsocketfail.explanation": "सिङ्क्रोनाइजेसन सर्भर सित जोणीन नाइ सकियो?", + "pad.modals.initsocketfail": "सर्भरमी पहुँच पुर्‍याउन नाइसकियो।", + "pad.modals.initsocketfail.explanation": "सिङ्क्रोनाइजेसन सर्भर सित जोणीन नाइ सकियो।", "pad.modals.initsocketfail.cause": "यो शायद तमरा ब्राउजर या इन्टरनेट जडान सित सम्बन्धित समस्याऽ कारणले होइ सकन्छ़।", "pad.modals.slowcommit.explanation": "सर्भर प्रत्युत्तर दिन्नारेन।", "pad.modals.slowcommit.cause": "यो नेटवर्क कनेक्टिविटी सङ्ङ सम्बन्धित समस्याऽ कारण ले होइसकन्छ।", @@ -72,13 +74,13 @@ "pad.modals.badChangeset.cause": "यो यक गलत सर्भर विन्यास या केइ और अप्रत्याशित चालचलनाऽ कारण़ ले होइसकन्छ। यदि तमलाई यो गल्ती हो भण्ण्या लागन्छ भँण्या, कृपया सेवा व्यवस्थापकलाई सम्पर्क अरऽ। सम्पादन चालु राख्दाइ दोसर्‍याँ जोणिन्या प्रयास अरऽ।", "pad.modals.corruptPad.explanation": "तमले उपयोग अद्द़ खोज्याऽ प्याड बिगण्योऽ छ।", "pad.modals.corruptPad.cause": "यो गलत सर्भर विन्यास या केइ और नसोच्याऽ चालचलनले होइसकन्छ। कृपया सेवा व्यवस्थापकलाई सम्पर्क अरऽ।", - "pad.modals.deleted": "मेटियाको", - "pad.modals.deleted.explanation": "यो प्याड हटाइसक्याको छ ।", - "pad.modals.disconnected": "तमरो जडान अवरुद्ध भयो ।", + "pad.modals.deleted": "मेटियाको।", + "pad.modals.deleted.explanation": "यो प्याड हटाइसकीरैछ।", + "pad.modals.disconnected": "तमरो जडान अवरुद्ध भयो।", "pad.modals.disconnected.explanation": "तमरो सर्भरसितको जडान अवरुद्ध भयो", "pad.modals.disconnected.cause": "सर्भर अनुपलब्ध होइसकन्छ। यदि यो हुनोइ रयाबर कृपया सेवा व्यवस्थापकलाई सूचित अरऽ।", - "pad.share": "यस प्यडलाई बाड्न्या", - "pad.share.readonly": "पड्या मात्तरै", + "pad.share": "यस प्याडलाई बाड्न्या", + "pad.share.readonly": "पड्‍ड्या मात्तरै", "pad.share.link": "लिङ्क", "pad.share.emebdcode": "URL थप्प्या", "pad.chat": "कुरणिकानी", @@ -117,13 +119,13 @@ "pad.userlist.deny": "अस्वीकार", "pad.userlist.approve": "अनुमोदन", "pad.editbar.clearcolors": "सङताइ कागताजमी है लेखक रङ्ङअन साप अद्द्या?", - "pad.impexp.importbutton": "ऐलै आयार अरऽ", + "pad.impexp.importbutton": "ऐलै आयात अरऽ", "pad.impexp.importing": "आयात अद्दाछ़...", "pad.impexp.confirmimport": "फाइल आयात़ ले प्याडओ अइलओ पाठ बदेलिन्या हो। तम ऐतिऱ बड्ड चाहन्छ भणिबर पक्का छऽ?", "pad.impexp.convertFailed": "एइ फाइललाई आयात अद्द नाइसक्यो। कृपया जुदोइ कागजात फर्याट प्रयोग अरऽ या नकल पेस्ट अरऽ", "pad.impexp.padHasData": "हम एइ फाइलाई आयात अद्दाइ असमर्थ छौँ क्याइकि एइ प्याडमी पैली अरीयाऽ फेलबदेल छन्, कृपया नयाँ प्याडमी आयात अरऽ", - "pad.impexp.uploadFailed": "अपलोड असफल, कृपया दोसर्‍याँ प्रयास अर:", + "pad.impexp.uploadFailed": "अपलोड असफल, कृपया दोसर्‍याँ प्रयास अरऽ", "pad.impexp.importfailed": "आयात असफल", - "pad.impexp.copypaste": "कृपया नकल सार अर:", + "pad.impexp.copypaste": "कृपया नकल सार अरऽ", "pad.impexp.exportdisabled": "{{type}} फर्म्याटमी निर्यात अक्षम अरीरैछ। विवरण खिलाइ कृपया तमरा संयन्त्र प्रशासकलाई सम्पर्क अर:।" } diff --git a/src/locales/nb.json b/src/locales/nb.json index 5c46b7de7..06293aa8b 100644 --- a/src/locales/nb.json +++ b/src/locales/nb.json @@ -4,7 +4,8 @@ "Laaknor", "Cocu", "Chameleon222", - "SuperPotato" + "SuperPotato", + "Jon Harald Søby" ] }, "index.newPad": "Ny Pad", @@ -59,6 +60,8 @@ "pad.modals.connected": "Tilkoblet.", "pad.modals.reconnecting": "Kobler til din blokk på nytt...", "pad.modals.forcereconnect": "Tving gjenoppkobling", + "pad.modals.reconnecttimer": "Prøver å koble til igjen", + "pad.modals.cancel": "Avbryt", "pad.modals.userdup": "Åpnet i nytt vindu", "pad.modals.userdup.explanation": "Denne blokken ser ut til å være åpnet i mer enn et nettleservindu på denne maskinen.", "pad.modals.userdup.advice": "Koble til igjen for å bruke dette vinduet i stedenfor.", diff --git a/src/locales/ru.json b/src/locales/ru.json index 2d92b1b61..2f0254918 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -61,6 +61,7 @@ "pad.modals.connected": "Подключен.", "pad.modals.reconnecting": "Повторное подключение к вашему документу", "pad.modals.forcereconnect": "Принудительное переподключение", + "pad.modals.cancel": "Отмена", "pad.modals.userdup": "Открыто в другом окне", "pad.modals.userdup.explanation": "Документ, возможно, открыт более чем в одном окне браузера на этом компьютере.", "pad.modals.userdup.advice": "Повторно подключить с использованием этого окна.", From cf686282ef69ba75ca4a9f9226fcbdd5a0698076 Mon Sep 17 00:00:00 2001 From: Luiza Pagliari Date: Thu, 11 May 2017 12:26:14 -0300 Subject: [PATCH 055/102] Do not use cookie for pad shortcuts Users still cannot choose which shortcuts they want to enable/disable, so it does not make sense (yet) to have a cookie with that preference. This can be reverted once we create an UI to change shortcuts, but PLEASE PLEASE PLEASE do not read the cookie every time handleKeyEvent is called!!! This is an adjustment to #2891. --- src/node/handler/PadMessageHandler.js | 1 + src/node/hooks/express/specialpages.js | 6 ----- src/static/js/ace2_inner.js | 33 +------------------------- 3 files changed, 2 insertions(+), 38 deletions(-) diff --git a/src/node/handler/PadMessageHandler.js b/src/node/handler/PadMessageHandler.js index 20b262f4e..b7ec7cb28 100644 --- a/src/node/handler/PadMessageHandler.js +++ b/src/node/handler/PadMessageHandler.js @@ -1197,6 +1197,7 @@ function handleClientReady(client, message) "userColor": authorColorId, "padId": message.padId, "padOptions": settings.padOptions, + "padShortcutEnabled": settings.padShortcutEnabled, "initialTitle": "Pad: " + message.padId, "opts": {}, // tell the client the number of the latest chat-message, which will be diff --git a/src/node/hooks/express/specialpages.js b/src/node/hooks/express/specialpages.js index e933a05a4..2840f82ca 100644 --- a/src/node/hooks/express/specialpages.js +++ b/src/node/hooks/express/specialpages.js @@ -48,12 +48,6 @@ exports.expressCreateServer = function (hook_name, args, cb) { res.cookie('language', settings.padOptions.lang); } - // Enable the pad shortcut keys from settings.json - if (settings.padShortcutEnabled !== undefined) - { - res.cookie('padShortcutEnabled', JSON.stringify(settings.padShortcutEnabled)); - } - // The below might break for pads being rewritten var isReadOnly = req.url.indexOf("/p/r.") === 0; diff --git a/src/static/js/ace2_inner.js b/src/static/js/ace2_inner.js index b6d4bd253..3b103988e 100644 --- a/src/static/js/ace2_inner.js +++ b/src/static/js/ace2_inner.js @@ -61,7 +61,6 @@ function Ace2Inner(){ var SkipList = require('./skiplist'); var undoModule = require('./undomodule').undoModule; var AttributeManager = require('./AttributeManager'); - var readCookie = require('./pad_utils').readCookie; var DEBUG = false; //$$ build script replaces the string "var DEBUG=true;//$$" with "var DEBUG=false;" // changed to false @@ -3641,37 +3640,6 @@ function Ace2Inner(){ function handleKeyEvent(evt) { - // Get the enabled shortcut keys - // If it can't find the cookie, use default values - // Cookie should normally be set - // See settings.json - var padShortcutEnabled = JSON.parse(decodeURIComponent(readCookie('padShortcutEnabled'))); - if (!padShortcutEnabled) - { - padShortcutEnabled = { - "altF9" : true, - "altC" : true, - "cmdShift2" : true, - "delete" : true, - "return" : true, - "cmdS" : true, - "tab" : true, - "cmdZ" : true, - "cmdY" : true, - "cmdI" : true, - "cmdB" : true, - "cmdU" : true, - "cmd5" : true, - "cmdShiftL" : true, - "cmdShiftN" : true, - "cmdShiftC" : true, - "cmdH" : true, - "ctrlHome" : true, - "pageUp" : true, - "pageDown" : true, - } - } - // if (DEBUG && window.DONT_INCORP) return; if (!isEditable) return; var type = evt.type; @@ -3755,6 +3723,7 @@ function Ace2Inner(){ specialHandled = _.contains(specialHandledInHook, true); } + var padShortcutEnabled = parent.parent.clientVars.padShortcutEnabled; if ((!specialHandled) && altKey && isTypeForSpecialKey && keyCode == 120 && padShortcutEnabled.altF9){ // Alt F9 focuses on the File Menu and/or editbar. // Note that while most editors use Alt F10 this is not desirable From 688e8f37a3a9557f5cec13692d97da01bfa19bf7 Mon Sep 17 00:00:00 2001 From: Luiza Pagliari Date: Thu, 11 May 2017 12:30:36 -0300 Subject: [PATCH 056/102] [fix] Fix format of settings template + add information about shortcuts There was an extra comma at the end of shortcut list, this was breaking Etherpad startup. This is an adjustment to #2891. --- settings.json.template | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/settings.json.template b/settings.json.template index 798ce0eff..e89f43036 100644 --- a/settings.json.template +++ b/settings.json.template @@ -75,26 +75,26 @@ /* Pad Shortcut Keys */ "padShortcutEnabled" : { - "altF9" : true, - "altC" : true, - "cmdShift2" : true, - "delete" : true, - "return" : true, - "cmdS" : true, - "tab" : true, - "cmdZ" : true, - "cmdY" : true, - "cmdI" : true, - "cmdB" : true, - "cmdU" : true, - "cmd5" : true, - "cmdShiftL" : true, - "cmdShiftN" : true, - "cmdShiftC" : true, - "cmdH" : true, - "ctrlHome" : true, - "pageUp" : true, - "pageDown" : true, + "altF9" : true, /* focus on the File Menu and/or editbar */ + "altC" : true, /* focus on the Chat window */ + "cmdShift2" : true, /* shows a gritter popup showing a line author */ + "delete" : true, + "return" : true, + "cmdS" : true, /* save a revision */ + "tab" : true, /* indent */ + "cmdZ" : true, /* undo/redo */ + "cmdY" : true, /* redo */ + "cmdI" : true, /* italic */ + "cmdB" : true, /* bold */ + "cmdU" : true, /* underline */ + "cmd5" : true, /* strike through */ + "cmdShiftL" : true, /* unordered list */ + "cmdShiftN" : true, /* ordered list */ + "cmdShiftC" : true, /* clear authorship */ + "cmdH" : true, /* backspace */ + "ctrlHome" : true, /* scroll to top of pad */ + "pageUp" : true, + "pageDown" : true }, /* Should we suppress errors from being visible in the default Pad Text? */ From 97038c2183c9f2c6f427825e121f841db01eb1c8 Mon Sep 17 00:00:00 2001 From: Luiza Pagliari Date: Thu, 11 May 2017 12:35:25 -0300 Subject: [PATCH 057/102] [fix] Fix shortcut enabling flag for 'ESC' This is an adjustment to #2891. --- settings.json.template | 1 + src/node/utils/Settings.js | 1 + src/static/js/ace2_inner.js | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/settings.json.template b/settings.json.template index e89f43036..b0bbfbde6 100644 --- a/settings.json.template +++ b/settings.json.template @@ -80,6 +80,7 @@ "cmdShift2" : true, /* shows a gritter popup showing a line author */ "delete" : true, "return" : true, + "esc" : true, /* in mozilla versions 14-19 avoid reconnecting pad */ "cmdS" : true, /* save a revision */ "tab" : true, /* indent */ "cmdZ" : true, /* undo/redo */ diff --git a/src/node/utils/Settings.js b/src/node/utils/Settings.js index 5060d28f4..e9b02449e 100644 --- a/src/node/utils/Settings.js +++ b/src/node/utils/Settings.js @@ -111,6 +111,7 @@ exports.padShortcutEnabled = { "delete" : true, "cmdShift2" : true, "return" : true, + "esc" : true, "cmdS" : true, "tab" : true, "cmdZ" : true, diff --git a/src/static/js/ace2_inner.js b/src/static/js/ace2_inner.js index 3b103988e..a0030c62f 100644 --- a/src/static/js/ace2_inner.js +++ b/src/static/js/ace2_inner.js @@ -3847,7 +3847,7 @@ function Ace2Inner(){ }, 0); specialHandled = true; } - if ((!specialHandled) && isTypeForSpecialKey && keyCode == 27 && padShortcutEnabled.cmdS) + if ((!specialHandled) && isTypeForSpecialKey && keyCode == 27 && padShortcutEnabled.esc) { // prevent esc key; // in mozilla versions 14-19 avoid reconnecting pad. From 0cb8d31e9569c3b80fb5847a664f28188f67a2ff Mon Sep 17 00:00:00 2001 From: Luiza Pagliari Date: Thu, 11 May 2017 14:56:09 -0300 Subject: [PATCH 058/102] [fix] Have one setting for each shortcut to create ordered list This is an adjustment to #2891. --- settings.json.template | 1 + src/node/utils/Settings.js | 1 + src/static/js/ace2_inner.js | 4 +- tests/frontend/specs/ordered_list.js | 98 ++++++++++++++++++++++++++-- 4 files changed, 96 insertions(+), 8 deletions(-) diff --git a/settings.json.template b/settings.json.template index b0bbfbde6..0cb10d50e 100644 --- a/settings.json.template +++ b/settings.json.template @@ -91,6 +91,7 @@ "cmd5" : true, /* strike through */ "cmdShiftL" : true, /* unordered list */ "cmdShiftN" : true, /* ordered list */ + "cmdShift1" : true, /* ordered list */ "cmdShiftC" : true, /* clear authorship */ "cmdH" : true, /* backspace */ "ctrlHome" : true, /* scroll to top of pad */ diff --git a/src/node/utils/Settings.js b/src/node/utils/Settings.js index e9b02449e..660b7afb3 100644 --- a/src/node/utils/Settings.js +++ b/src/node/utils/Settings.js @@ -122,6 +122,7 @@ exports.padShortcutEnabled = { "cmd5" : true, "cmdShiftL" : true, "cmdShiftN" : true, + "cmdShift1" : true, "cmdShiftC" : true, "cmdH" : true, "ctrlHome" : true, diff --git a/src/static/js/ace2_inner.js b/src/static/js/ace2_inner.js index a0030c62f..b3759e528 100644 --- a/src/static/js/ace2_inner.js +++ b/src/static/js/ace2_inner.js @@ -3939,9 +3939,9 @@ function Ace2Inner(){ doInsertUnorderedList() specialHandled = true; } - if ((!specialHandled) && isTypeForCmdKey && (String.fromCharCode(which).toLowerCase() == "n" || String.fromCharCode(which) == 1) && (evt.metaKey || evt.ctrlKey) && evt.shiftKey && padShortcutEnabled.cmdShiftN) + if ((!specialHandled) && isTypeForCmdKey && ((String.fromCharCode(which).toLowerCase() == "n" && padShortcutEnabled.cmdShiftN) || (String.fromCharCode(which) == 1 && padShortcutEnabled.cmdShift1)) && (evt.metaKey || evt.ctrlKey) && evt.shiftKey) { - // cmd-shift-N (orderedlist) + // cmd-shift-N and cmd-shift-1 (orderedlist) fastIncorp(9); evt.preventDefault(); doInsertOrderedList() diff --git a/tests/frontend/specs/ordered_list.js b/tests/frontend/specs/ordered_list.js index ca7d755e9..57196fefe 100644 --- a/tests/frontend/specs/ordered_list.js +++ b/tests/frontend/specs/ordered_list.js @@ -5,8 +5,8 @@ describe("assign ordered list", function(){ this.timeout(60000); }); - it("insert ordered list text", function(done){ - var inner$ = helper.padInner$; + it("inserts ordered list text", function(done){ + var inner$ = helper.padInner$; var chrome$ = helper.padChrome$; var $insertorderedlistButton = chrome$(".buttonicon-insertorderedlist"); @@ -17,8 +17,72 @@ describe("assign ordered list", function(){ }).done(done); }); + context('when user presses Ctrl+Shift+N', function() { + context('and pad shortcut is enabled', function() { + beforeEach(function() { + makeSureShortcutIsEnabled('cmdShiftN'); + triggerCtrlShiftShortcut('N'); + }); + + it('inserts unordered list', function(done) { + helper.waitFor(function() { + return helper.padInner$('div').first().find('ol li').length === 1; + }).done(done); + }); + }); + + context('and pad shortcut is disabled', function() { + beforeEach(function() { + makeSureShortcutIsDisabled('cmdShiftN'); + triggerCtrlShiftShortcut('N'); + }); + + it('does not insert unordered list', function(done) { + helper.waitFor(function() { + return helper.padInner$('div').first().find('ol li').length === 1; + }).done(function() { + expect().fail(function() { return 'Unordered list inserted, should ignore shortcut' }); + }).fail(function() { + done(); + }); + }); + }); + }); + + context('when user presses Ctrl+Shift+1', function() { + context('and pad shortcut is enabled', function() { + beforeEach(function() { + makeSureShortcutIsEnabled('cmdShift1'); + triggerCtrlShiftShortcut('1'); + }); + + it('inserts unordered list', function(done) { + helper.waitFor(function() { + return helper.padInner$('div').first().find('ol li').length === 1; + }).done(done); + }); + }); + + context('and pad shortcut is disabled', function() { + beforeEach(function() { + makeSureShortcutIsDisabled('cmdShift1'); + triggerCtrlShiftShortcut('1'); + }); + + it('does not insert unordered list', function(done) { + helper.waitFor(function() { + return helper.padInner$('div').first().find('ol li').length === 1; + }).done(function() { + expect().fail(function() { return 'Unordered list inserted, should ignore shortcut' }); + }).fail(function() { + done(); + }); + }); + }); + }); + xit("issue #1125 keeps the numbered list on enter for the new line - EMULATES PASTING INTO A PAD", function(done){ - var inner$ = helper.padInner$; + var inner$ = helper.padInner$; var chrome$ = helper.padChrome$; var $insertorderedlistButton = chrome$(".buttonicon-insertorderedlist"); @@ -26,9 +90,9 @@ describe("assign ordered list", function(){ //type a bit, make a line break and type again var $firstTextElement = inner$("div span").first(); - $firstTextElement.sendkeys('line 1'); - $firstTextElement.sendkeys('{enter}'); - $firstTextElement.sendkeys('line 2'); + $firstTextElement.sendkeys('line 1'); + $firstTextElement.sendkeys('{enter}'); + $firstTextElement.sendkeys('line 2'); $firstTextElement.sendkeys('{enter}'); helper.waitFor(function(){ @@ -44,4 +108,26 @@ describe("assign ordered list", function(){ done(); }); }); + + var triggerCtrlShiftShortcut = function(shortcutChar) { + var inner$ = helper.padInner$; + if(inner$(window)[0].bowser.firefox || inner$(window)[0].bowser.modernIE) { // if it's a mozilla or IE + var evtType = "keypress"; + }else{ + var evtType = "keydown"; + } + var e = inner$.Event(evtType); + e.ctrlKey = true; + e.shiftKey = true; + e.which = shortcutChar.toString().charCodeAt(0); + inner$("#innerdocbody").trigger(e); + } + + var makeSureShortcutIsDisabled = function(shortcut) { + helper.padChrome$.window.clientVars.padShortcutEnabled[shortcut] = false; + } + var makeSureShortcutIsEnabled = function(shortcut) { + helper.padChrome$.window.clientVars.padShortcutEnabled[shortcut] = true; + } + }); From 894ebffcaf3d5fcab957f5e40d1fc94359003d54 Mon Sep 17 00:00:00 2001 From: Luiza Pagliari Date: Fri, 12 May 2017 07:03:40 -0300 Subject: [PATCH 059/102] [fix] Do not close ANY "force reconnect" message Fix previous commit. As "force reconnect" buttons have all the same id on DOM, on the previous commit we were only disallowing the first button with that id on DOM -- "userdup" -- to be closed by a click on editor. Casually the tests were using the same error to simulate a "force reconnect", so even the tests were not getting the issue. --- src/static/js/pad_editbar.js | 2 +- tests/frontend/specs/pad_modal.js | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/static/js/pad_editbar.js b/src/static/js/pad_editbar.js index b2aade466..9cf357aad 100644 --- a/src/static/js/pad_editbar.js +++ b/src/static/js/pad_editbar.js @@ -271,7 +271,7 @@ var padeditbar = (function() var module = $("#" + thisModuleName); //skip any "force reconnect" message - var isAForceReconnectMessage = module.find('#forcereconnect').is(':visible'); + var isAForceReconnectMessage = module.find('button#forcereconnect:visible').length > 0; if(isAForceReconnectMessage) continue; diff --git a/tests/frontend/specs/pad_modal.js b/tests/frontend/specs/pad_modal.js index 15eb8ac86..80752e4b8 100644 --- a/tests/frontend/specs/pad_modal.js +++ b/tests/frontend/specs/pad_modal.js @@ -1,15 +1,11 @@ describe('Pad modal', function() { context('when modal is a "force reconnect" message', function() { - var MODAL_SELECTOR = '#connectivity .userdup'; - - var padId, $originalPadFrame; + var MODAL_SELECTOR = '#connectivity .slowcommit'; beforeEach(function(done) { - padId = helper.newPad(function() { - // open same pad on another iframe, to force userdup error - var $otherIframeWithSamePad = $(''); - $originalPadFrame = $('#iframe-container iframe'); - $otherIframeWithSamePad.insertAfter($originalPadFrame); + helper.newPad(function() { + // force a "slowcommit" error + helper.padChrome$.window.pad.handleChannelStateChange('DISCONNECTED', 'slowcommit'); // wait for modal to be displayed var $modal = helper.padChrome$(MODAL_SELECTOR); From fc89034a555d1708a70f5007b4e6c0bc2641d8a4 Mon Sep 17 00:00:00 2001 From: Luiza Pagliari Date: Thu, 18 May 2017 18:52:14 -0300 Subject: [PATCH 060/102] [feat] New server-side hook: padCopy Let plugins know when a pad is copied. --- doc/api/hooks_server-side.md | 20 +++++++++++++++++++- src/node/db/Pad.js | 5 +++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/doc/api/hooks_server-side.md b/doc/api/hooks_server-side.md index 8a4ad978c..d4e836404 100644 --- a/doc/api/hooks_server-side.md +++ b/doc/api/hooks_server-side.md @@ -106,7 +106,7 @@ Here you can add custom toolbar items that will be available in the toolbar conf Usage examples: -* [https://github.com/tiblu/ep_authorship_toggle]() +* https://github.com/tiblu/ep_authorship_toggle ## padCreate Called from: src/node/db/Pad.js @@ -137,6 +137,20 @@ Things in context: This hook gets called when an existing pad was updated. +## padCopy +Called from: src/node/db/Pad.js + +Things in context: + +1. originalPad - the source pad instance +2. destinationID - the id of the pad copied from originalPad + +This hook gets called when an existing pad was copied. + +Usage examples: + +* https://github.com/ether/ep_comments + ## padRemove Called from: src/node/db/Pad.js @@ -146,6 +160,10 @@ Things in context: This hook gets called when an existing pad was removed/deleted. +Usage examples: + +* https://github.com/ether/ep_comments + ## socketio Called from: src/node/hooks/express/socketio.js diff --git a/src/node/db/Pad.js b/src/node/db/Pad.js index 5d26f470c..d44cb7b36 100644 --- a/src/node/db/Pad.js +++ b/src/node/db/Pad.js @@ -592,6 +592,11 @@ Pad.prototype.copy = function copy(destinationID, force, callback) { setTimeout(function(){ padManager.getPad(destinationID, null, callback) // this runs too early. },10); + }, + // let the plugins know the pad was copied + function(callback) { + hooks.callAll('padCopy', { 'originalPad': _this, 'destinationID': destinationID }); + callback(); } // series ], function(err) From 66df56559c19e38f261fa87569a24719328e8e33 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Sat, 20 May 2017 10:53:31 +0200 Subject: [PATCH 061/102] Localisation updates from https://translatewiki.net. --- src/locales/af.json | 23 +++++++++++++++++------ src/locales/hy.json | 1 + src/locales/pl.json | 6 ++++-- src/locales/ru.json | 4 +++- 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/locales/af.json b/src/locales/af.json index eb04e479c..1a9ce4cc4 100644 --- a/src/locales/af.json +++ b/src/locales/af.json @@ -1,7 +1,8 @@ { "@metadata": { "authors": [ - "Naudefj" + "Naudefj", + "Fwolff" ] }, "index.newPad": "Nuwe pad", @@ -9,13 +10,15 @@ "pad.toolbar.bold.title": "Vet (Ctrl-B)", "pad.toolbar.italic.title": "Kursief (Ctrl-I)", "pad.toolbar.underline.title": "Onderstreep (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Deurgehaal", - "pad.toolbar.ol.title": "Geordende lys", - "pad.toolbar.ul.title": "Ongeordende lys", - "pad.toolbar.indent.title": "Indenteer", - "pad.toolbar.unindent.title": "Verklein indentering", + "pad.toolbar.strikethrough.title": "Deurgehaal (Ctrl+5)", + "pad.toolbar.ol.title": "Geordende lys (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Ongeordende lys (Ctrl+Shift+L)", + "pad.toolbar.indent.title": "Indenteer (TAB)", + "pad.toolbar.unindent.title": "Verklein indentering (Shift+TAB)", "pad.toolbar.undo.title": "Ongedaan maak (Ctrl-Z)", "pad.toolbar.redo.title": "Herdoen (Ctrl-Y)", + "pad.toolbar.clearAuthorship.title": "Verwyder skrywers se kleure (Ctrl+Shift+C)", + "pad.toolbar.import_export.title": "Voer in/uit van/na verskillende lêerformate", "pad.toolbar.settings.title": "Voorkeure", "pad.colorpicker.save": "Stoor", "pad.colorpicker.cancel": "Kanselleer", @@ -23,8 +26,16 @@ "pad.settings.myView": "My oorsig", "pad.settings.fontType.normal": "Normaal", "pad.settings.fontType.monospaced": "Monospasie", + "pad.settings.language": "Taal:", + "pad.importExport.import_export": "Voer in/uit", + "pad.importExport.import": "Laai enige tekslêer of dokument op", + "pad.importExport.importSuccessful": "Sukses!", "pad.importExport.exporthtml": "HTML", + "pad.importExport.exportplain": "Skoon teks", + "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", + "pad.importExport.exportopen": "ODF (Open Document-formaat)", + "pad.modals.cancel": "Kanselleer", "pad.modals.userdup.advice": "Maak weer 'n verbinding as u die venster wil gebruik.", "pad.modals.unauth": "Nie toegestaan", "pad.modals.deleted": "Geskrap.", diff --git a/src/locales/hy.json b/src/locales/hy.json index 672905c5a..20e0026ce 100644 --- a/src/locales/hy.json +++ b/src/locales/hy.json @@ -29,6 +29,7 @@ "pad.importExport.exportpdf": "PDF", "pad.modals.connected": "Կապված է", "pad.modals.forcereconnect": "Հարկադիր վերամիավորել", + "pad.modals.cancel": "Չեղարկել", "pad.modals.userdup": "Բաց է մյուս պատուհանում", "pad.modals.initsocketfail": "Սերվերը անհասանելի է ։", "pad.modals.slowcommit.explanation": "Սերվերը չի պատասխանում։", diff --git a/src/locales/pl.json b/src/locales/pl.json index 85bbf4745..2c07ef173 100644 --- a/src/locales/pl.json +++ b/src/locales/pl.json @@ -19,7 +19,7 @@ "pad.toolbar.ol.title": "Lista uporządkowana (Ctrl+Shift+N)", "pad.toolbar.ul.title": "Lista nieuporządkowana (Ctrl+Shift+L)", "pad.toolbar.indent.title": "Wcięcie (TAB)", - "pad.toolbar.unindent.title": "Wcięcie (Shift + TAB)", + "pad.toolbar.unindent.title": "Usunięcie wcięcia (Shift + TAB)", "pad.toolbar.undo.title": "Cofnij (Ctrl-Z)", "pad.toolbar.redo.title": "Ponów (Ctrl-Y)", "pad.toolbar.clearAuthorship.title": "Usuń kolory autorów (Ctrl+Shift+C)", @@ -32,7 +32,7 @@ "pad.colorpicker.save": "Zapisz", "pad.colorpicker.cancel": "Anuluj", "pad.loading": "Ładowanie...", - "pad.noCookie": "Nie znaleziono pliku cookie. Proszę zezwolić pliki cookie w przeglądarce!", + "pad.noCookie": "Nie znaleziono pliku cookie. Proszę zezwolić na pliki cookie w przeglądarce!", "pad.passwordRequired": "Musisz podać hasło aby uzyskać dostęp do tego dokumentu", "pad.permissionDenied": "Nie masz uprawnień dostępu do tego dokumentu", "pad.wrongPassword": "Nieprawidłowe hasło", @@ -62,6 +62,8 @@ "pad.modals.connected": "Połączony.", "pad.modals.reconnecting": "Ponowne łączenie z dokumentem...", "pad.modals.forcereconnect": "Wymuś ponowne połączenie", + "pad.modals.reconnecttimer": "Trwa próba ponownego połączenia", + "pad.modals.cancel": "Anuluj", "pad.modals.userdup": "Otwarty w innym oknie", "pad.modals.userdup.explanation": "Ten dokument prawdopodobnie został otwarty w więcej niż jednym oknie przeglądarki.", "pad.modals.userdup.advice": "Połącz ponownie przy użyciu tego okna.", diff --git a/src/locales/ru.json b/src/locales/ru.json index 2f0254918..b9fbc3c82 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -6,7 +6,8 @@ "Eleferen", "Okras", "Volkov", - "Nzeemin" + "Nzeemin", + "Facenapalm" ] }, "index.newPad": "Создать", @@ -61,6 +62,7 @@ "pad.modals.connected": "Подключен.", "pad.modals.reconnecting": "Повторное подключение к вашему документу", "pad.modals.forcereconnect": "Принудительное переподключение", + "pad.modals.reconnecttimer": "Попытка переподключения", "pad.modals.cancel": "Отмена", "pad.modals.userdup": "Открыто в другом окне", "pad.modals.userdup.explanation": "Документ, возможно, открыт более чем в одном окне браузера на этом компьютере.", From c7dac38af5db1cc1dbc8cf34547e5ead999332db Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Sun, 21 May 2017 09:52:24 +0200 Subject: [PATCH 062/102] Localisation updates from https://translatewiki.net. --- src/locales/nl.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/locales/nl.json b/src/locales/nl.json index b01df7a33..727e8abec 100644 --- a/src/locales/nl.json +++ b/src/locales/nl.json @@ -59,6 +59,8 @@ "pad.modals.connected": "Verbonden.", "pad.modals.reconnecting": "Opnieuw verbinding maken met uw pad...", "pad.modals.forcereconnect": "Opnieuw verbinden", + "pad.modals.reconnecttimer": "Proberen te verbinden over", + "pad.modals.cancel": "Annuleren", "pad.modals.userdup": "In een ander venster geopend", "pad.modals.userdup.explanation": "Dit pad is meer dan één keer geopend in een browservenster op deze computer.", "pad.modals.userdup.advice": "Maak opnieuw verbinding als u dit venster wilt gebruiken.", From faefa8a9efde5394a1bfbced295e2ed1565e5ab3 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 29 May 2017 07:50:59 +0200 Subject: [PATCH 063/102] Localisation updates from https://translatewiki.net. --- src/locales/bs.json | 87 +++++++++++++++++++++++++++++++++++++++++++++ src/locales/is.json | 2 ++ src/locales/uk.json | 4 ++- 3 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 src/locales/bs.json diff --git a/src/locales/bs.json b/src/locales/bs.json new file mode 100644 index 000000000..cdc72787f --- /dev/null +++ b/src/locales/bs.json @@ -0,0 +1,87 @@ +{ + "@metadata": { + "authors": [ + "Edinwiki", + "Srdjan m" + ] + }, + "pad.toolbar.bold.title": "Podebljano (Ctrl+B)", + "pad.toolbar.italic.title": "Ukošeno (Ctrl+I)", + "pad.toolbar.underline.title": "Podvučeno (Ctrl+U)", + "pad.toolbar.strikethrough.title": "Precrtano (Ctrl+5)", + "pad.toolbar.ol.title": "Poredani spisak (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Neporedani spisak (Ctrl+Shift+L)", + "pad.toolbar.indent.title": "Uvučeno (TAB)", + "pad.toolbar.unindent.title": "Izvučeno (Shift+TAB)", + "pad.toolbar.undo.title": "Poništi (Ctrl+Z)", + "pad.toolbar.redo.title": "Ponovi (Ctrl+Y)", + "pad.toolbar.timeslider.title": "Historijski pregled", + "pad.toolbar.settings.title": "Postavke", + "pad.colorpicker.save": "Sačuvaj", + "pad.colorpicker.cancel": "Otkaži", + "pad.loading": "Učitavam...", + "pad.wrongPassword": "Pogrešna lozinka", + "pad.settings.myView": "Moj prikaz", + "pad.settings.stickychat": "Ćaskanje uvijek na ekranu", + "pad.settings.chatandusers": "Prikaži ćaskanje i korisnike", + "pad.settings.linenocheck": "Brojevi redova", + "pad.settings.rtlcheck": "Da prikažem sadržaj zdesna ulijevo?", + "pad.settings.fontType": "Vrsta fonta:", + "pad.settings.fontType.normal": "Normalno", + "pad.settings.globalView": "Globalni prikaz", + "pad.settings.language": "Jezik:", + "pad.importExport.import_export": "Uvoz/Izvoz", + "pad.importExport.importSuccessful": "Uspješno!", + "pad.importExport.exportetherpad": "Etherpad", + "pad.importExport.exporthtml": "HTML", + "pad.importExport.exportplain": "Obični tekst", + "pad.importExport.exportword": "Microsoft Word", + "pad.importExport.exportpdf": "PDF", + "pad.importExport.exportopen": "ODF (Open Document Format)", + "pad.modals.connected": "Spojeno.", + "pad.modals.forcereconnect": "Prisilno se ponovo poveži", + "pad.modals.reconnecttimer": "Pokušavam se ponovo povezati", + "pad.modals.cancel": "Otkaži", + "pad.modals.userdup": "Otvoreno u drugom prozoru", + "pad.modals.unauth": "Niste ovlašteni", + "pad.modals.initsocketfail": "Server je nedostupan.", + "pad.modals.initsocketfail.explanation": "Ne mogu se povezati sa sinhronizacijskim serverom.", + "pad.modals.slowcommit.explanation": "Server se ne odaziva.", + "pad.modals.deleted": "Obrisano.", + "pad.modals.disconnected": "Veza je prekinuta.", + "pad.modals.disconnected.explanation": "Izgubljena je veza sa serverom", + "pad.modals.disconnected.cause": "Moguće je da server nije dostupan. Obavijestite administratora ako se ovo nastavi dešavati.", + "pad.share.readonly": "Samo za čitanje", + "pad.share.link": "Link", + "pad.share.emebdcode": "URL za ugradnju", + "pad.chat": "Ćaskanje", + "pad.chat.loadmessages": "Učitaj više poruka", + "timeslider.pageTitle": "{{appTitle}} Historijski pregled", + "timeslider.toolbar.authors": "Autori:", + "timeslider.toolbar.authorsList": "Nema autora", + "timeslider.toolbar.exportlink.title": "Izvoz", + "timeslider.exportCurrent": "Izvezi trenutnu verziju kao:", + "timeslider.version": "Verzija {{version}}", + "timeslider.saved": "Sačuvano na datum {{day}}. {{month}} {{year}}", + "timeslider.month.january": "januar", + "timeslider.month.february": "februar", + "timeslider.month.march": "mart", + "timeslider.month.april": "april", + "timeslider.month.may": "maj", + "timeslider.month.june": "juni", + "timeslider.month.july": "juli", + "timeslider.month.august": "august", + "timeslider.month.september": "septembar", + "timeslider.month.october": "oktobar", + "timeslider.month.november": "novembar", + "timeslider.month.december": "decembar", + "pad.userlist.entername": "Upišite svoje ime", + "pad.userlist.unnamed": "bez imena", + "pad.userlist.guest": "Gost", + "pad.userlist.deny": "Odbij", + "pad.userlist.approve": "Odobri", + "pad.impexp.importbutton": "Uvezi odmah", + "pad.impexp.importing": "Uvozim...", + "pad.impexp.uploadFailed": "Postavljanje nije uspjelo. Pokušajte ponovo", + "pad.impexp.importfailed": "Uvoz neuspješan" +} diff --git a/src/locales/is.json b/src/locales/is.json index 61065cb75..3d51bd72a 100644 --- a/src/locales/is.json +++ b/src/locales/is.json @@ -57,6 +57,8 @@ "pad.modals.connected": "Tengt.", "pad.modals.reconnecting": "Endurtengist skrifblokkinni þinni...", "pad.modals.forcereconnect": "Þvinga endurtengingu", + "pad.modals.reconnecttimer": "Reyni aftur að tengjast eftir", + "pad.modals.cancel": "Hætta við", "pad.modals.userdup": "Opnað í öðrum glugga", "pad.modals.userdup.explanation": "Þessi skrifblokk virðist vera opin í fleiri en einum vafraglugga á þessari tölvu.", "pad.modals.userdup.advice": "Endurtengdu til að nota þennan glugga í staðinn.", diff --git a/src/locales/uk.json b/src/locales/uk.json index d5384a554..e4472ef28 100644 --- a/src/locales/uk.json +++ b/src/locales/uk.json @@ -7,7 +7,8 @@ "Steve.rusyn", "SteveR", "Lxlalexlxl", - "Григорій Пугач" + "Григорій Пугач", + "Bunyk" ] }, "index.newPad": "Створити", @@ -62,6 +63,7 @@ "pad.modals.connected": "З'єднано.", "pad.modals.reconnecting": "Перепідлючення до Вашого документу..", "pad.modals.forcereconnect": "Примусове перепідключення", + "pad.modals.cancel": "Скасувати", "pad.modals.userdup": "Відкрито в іншому вікні", "pad.modals.userdup.explanation": "Документ, можливо, відкрито більш ніж в одному вікні браузера на цьому комп'ютері.", "pad.modals.userdup.advice": "Перепідключитись використовуючи це вікно.", From fcde66050e960340bcb9d2479f76548c99644644 Mon Sep 17 00:00:00 2001 From: Jonah Duckles Date: Tue, 30 May 2017 13:34:07 +1200 Subject: [PATCH 064/102] Fix markdown H1 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b4120a3ce..63b970b1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -#1.6.1 +# 1.6.1 * NEW: Hook aceRegisterNonScrollableEditEvents to register events that shouldn't scroll * NEW: Added 'item' parameter to registerAceCommand Hook * NEW: Added LibreJS support From 1c26ac5c6fd09a64acede6983cc5c1ace43ffc7d Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 1 Jun 2017 07:15:35 +0200 Subject: [PATCH 065/102] Localisation updates from https://translatewiki.net. --- src/locales/bs.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/locales/bs.json b/src/locales/bs.json index cdc72787f..82496680b 100644 --- a/src/locales/bs.json +++ b/src/locales/bs.json @@ -20,6 +20,7 @@ "pad.colorpicker.save": "Sačuvaj", "pad.colorpicker.cancel": "Otkaži", "pad.loading": "Učitavam...", + "pad.noCookie": "Kolačić nije pronađen. Dozvolite kolačiće u Vašem pregledniku!", "pad.wrongPassword": "Pogrešna lozinka", "pad.settings.myView": "Moj prikaz", "pad.settings.stickychat": "Ćaskanje uvijek na ekranu", From 1db87e11339eaf0f39c90435884a3e6473ef0c3a Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 5 Jun 2017 07:34:21 +0200 Subject: [PATCH 066/102] Localisation updates from https://translatewiki.net. --- src/locales/bs.json | 2 ++ src/locales/fr.json | 2 +- src/locales/ia.json | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/locales/bs.json b/src/locales/bs.json index 82496680b..e4fb57469 100644 --- a/src/locales/bs.json +++ b/src/locales/bs.json @@ -32,6 +32,7 @@ "pad.settings.globalView": "Globalni prikaz", "pad.settings.language": "Jezik:", "pad.importExport.import_export": "Uvoz/Izvoz", + "pad.importExport.import": "Postavite bilo koju tekstualnu datoteku ili dokument", "pad.importExport.importSuccessful": "Uspješno!", "pad.importExport.exportetherpad": "Etherpad", "pad.importExport.exporthtml": "HTML", @@ -44,6 +45,7 @@ "pad.modals.reconnecttimer": "Pokušavam se ponovo povezati", "pad.modals.cancel": "Otkaži", "pad.modals.userdup": "Otvoreno u drugom prozoru", + "pad.modals.userdup.advice": "Ponovo se povežite da biste koristili ovaj prozor.", "pad.modals.unauth": "Niste ovlašteni", "pad.modals.initsocketfail": "Server je nedostupan.", "pad.modals.initsocketfail.explanation": "Ne mogu se povezati sa sinhronizacijskim serverom.", diff --git a/src/locales/fr.json b/src/locales/fr.json index 2d311b054..4213e3460 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -86,7 +86,7 @@ "pad.modals.unauth": "Non autorisé", "pad.modals.unauth.explanation": "Vos permissions ont été changées lors de l'affichage de cette page. Essayez de vous reconnecter.", "pad.modals.looping.explanation": "Nous éprouvons un problème de communication au serveur de synchronisation.", - "pad.modals.looping.cause": "Il est possible que vous soyez connecté avec un pare-feu ou un proxy incompatible.", + "pad.modals.looping.cause": "Il est possible que vous soyez connecté avec un pare-feu ou un mandataire incompatible.", "pad.modals.initsocketfail": "Le serveur est introuvable.", "pad.modals.initsocketfail.explanation": "Impossible de se connecter au serveur de synchronisation.", "pad.modals.initsocketfail.cause": "Ceci est probablement dû à un problème avec votre navigateur ou votre connexion internet.", diff --git a/src/locales/ia.json b/src/locales/ia.json index 64d3bf6e1..9a3fd31ec 100644 --- a/src/locales/ia.json +++ b/src/locales/ia.json @@ -56,6 +56,8 @@ "pad.modals.connected": "Connectite.", "pad.modals.reconnecting": "Reconnecte a tu pad…", "pad.modals.forcereconnect": "Fortiar reconnexion", + "pad.modals.reconnecttimer": "Tentativa de reconnexion in", + "pad.modals.cancel": "Cancellar", "pad.modals.userdup": "Aperte in un altere fenestra", "pad.modals.userdup.explanation": "Iste pad pare esser aperte in plus de un fenestra de navigator in iste computator.", "pad.modals.userdup.advice": "Reconnecte pro usar iste fenestra.", From 0fdb031839b6e156d0f80393c8a64ea80b9f8de4 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 15 Jun 2017 07:47:04 +0200 Subject: [PATCH 067/102] Localisation updates from https://translatewiki.net. --- src/locales/pl.json | 11 ++++++----- src/locales/uk.json | 4 +++- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/locales/pl.json b/src/locales/pl.json index 2c07ef173..c26328786 100644 --- a/src/locales/pl.json +++ b/src/locales/pl.json @@ -7,7 +7,8 @@ "Woytecr", "Macofe", "Pan Cube", - "Mateon1" + "Mateon1", + "Teeed" ] }, "index.newPad": "Nowy dokument", @@ -75,9 +76,9 @@ "pad.modals.initsocketfail.explanation": "Nie udało się połączyć z serwerem synchronizacji.", "pad.modals.initsocketfail.cause": "Prawdopodobnie jest to spowodowane problemami z przeglądarką lub połączeniem internetowym.", "pad.modals.slowcommit.explanation": "Serwer nie odpowiada.", - "pad.modals.slowcommit.cause": "Może być to spowodowane problemami z Twoim połączeniem z siecią.", - "pad.modals.badChangeset.explanation": "Edycja, którą wykonałeś, została niewłaściwie zakwalifikowana przez serwer synchronizacji.", - "pad.modals.badChangeset.cause": "Może być to spowodowane złą konfiguracją serwera lub innym nieoczekiwanym zachowaniem. Skontaktuj się z administratorem serwisu, jeżeli wydaje Ci się, że to jest błąd. Spróbuj ponownie połączyć się aby kontynuować edycję.", + "pad.modals.slowcommit.cause": "Może być to spowodowane problemami z Twoim połączeniem sieciowym.", + "pad.modals.badChangeset.explanation": "Edycja, którą wykonałeś, została uznana przez serwer synchronizacji jako niepoprawna.", + "pad.modals.badChangeset.cause": "Może być to spowodowane złą konfiguracją serwera lub innym nieoczekiwanym zachowaniem. Skontaktuj się z administratorem serwisu, jeżeli wydaje Ci się, że to jest błąd. Spróbuj połączyć się ponownie aby kontynuować edycję.", "pad.modals.corruptPad.explanation": "Dokument, do którego próbujesz uzyskać dostęp, jest uszkodzony.", "pad.modals.corruptPad.cause": "Może być to spowodowane złą konfiguracją serwera lub innym nieoczekiwanym zachowaniem. Skontaktuj się z administratorem serwisu.", "pad.modals.deleted": "Usunięto.", @@ -100,7 +101,7 @@ "timeslider.exportCurrent": "Eksportuj bieżącą wersję jako:", "timeslider.version": "Wersja {{version}}", "timeslider.saved": "Zapisano {{day}} {{month}} {{year}}", - "timeslider.playPause": "Odtwarzaj / pauzuj zawartość dokumentu", + "timeslider.playPause": "Odtwarzaj / zatrzymaj przewijanie historii dokumentu", "timeslider.backRevision": "Przejdź do poprzedniej wersji dokumentu", "timeslider.forwardRevision": "Przejdź do następnej wersji dokumentu", "timeslider.dateformat": "{{year}}-{{month}}-{{day}} {{hours}}:{{minutes}}:{{seconds}}", diff --git a/src/locales/uk.json b/src/locales/uk.json index e4472ef28..9f89e5021 100644 --- a/src/locales/uk.json +++ b/src/locales/uk.json @@ -8,7 +8,8 @@ "SteveR", "Lxlalexlxl", "Григорій Пугач", - "Bunyk" + "Bunyk", + "Piramidion" ] }, "index.newPad": "Створити", @@ -63,6 +64,7 @@ "pad.modals.connected": "З'єднано.", "pad.modals.reconnecting": "Перепідлючення до Вашого документу..", "pad.modals.forcereconnect": "Примусове перепідключення", + "pad.modals.reconnecttimer": "Триває спроба відновлення з'єднання", "pad.modals.cancel": "Скасувати", "pad.modals.userdup": "Відкрито в іншому вікні", "pad.modals.userdup.explanation": "Документ, можливо, відкрито більш ніж в одному вікні браузера на цьому комп'ютері.", From 2e77a286958277141b837b8c1705361362345ce6 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 19 Jun 2017 14:10:49 +0200 Subject: [PATCH 068/102] Localisation updates from https://translatewiki.net. --- src/locales/bg.json | 62 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/locales/bg.json diff --git a/src/locales/bg.json b/src/locales/bg.json new file mode 100644 index 000000000..d1403fe7e --- /dev/null +++ b/src/locales/bg.json @@ -0,0 +1,62 @@ +{ + "@metadata": { + "authors": [ + "Vodnokon4e" + ] + }, + "index.newPad": "Нов пад", + "index.createOpenPad": "или създаване/отваряне на пад с име:", + "pad.toolbar.bold.title": "Получер (Ctrl+B)", + "pad.toolbar.italic.title": "Наклонен (Ctrl+I)", + "pad.toolbar.underline.title": "Подчертан (Ctrl+U)", + "pad.toolbar.strikethrough.title": "Зачеркнат (Ctrl+5)", + "pad.toolbar.ol.title": "Подреден списък (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Неподреден списък (Ctrl+Shift+L)", + "pad.toolbar.indent.title": "Отстъп (TAB)", + "pad.toolbar.unindent.title": "Премахване на отстъпа (Shift+TAB)", + "pad.toolbar.undo.title": "Отмяна (Ctrl+Z)", + "pad.toolbar.redo.title": "Връщане (Ctrl+Y)", + "pad.toolbar.settings.title": "Настройки", + "pad.colorpicker.save": "Съхраняване", + "pad.colorpicker.cancel": "Отказване", + "pad.loading": "Зареждане...", + "pad.wrongPassword": "Неправилна парола", + "pad.settings.language": "Език:", + "pad.importExport.exportetherpad": "Etherpad", + "pad.importExport.exporthtml": "HTML", + "pad.importExport.exportplain": "Обикновен текст", + "pad.importExport.exportword": "Microsoft Word", + "pad.importExport.exportpdf": "PDF", + "pad.importExport.exportopen": "ODF (Open Document Format)", + "pad.modals.userdup": "Отворен в друг прозорец", + "pad.modals.initsocketfail": "Сървърът е недостъпен.", + "pad.modals.slowcommit.explanation": "Сървърът не отговаря.", + "pad.modals.slowcommit.cause": "Това може да се дължи на проблеми с мрежовите връзки.", + "pad.modals.deleted": "Изтрито.", + "pad.share.readonly": "Само за четене", + "pad.share.link": "Препратка", + "pad.share.emebdcode": "Постави URL", + "pad.chat": "Чат", + "pad.chat.title": "Отваряне на чат за този пад.", + "pad.chat.loadmessages": "Зареждане на повече съобщения", + "timeslider.toolbar.returnbutton": "Връщане към пада", + "timeslider.toolbar.authors": "Автори:", + "timeslider.toolbar.authorsList": "Няма автори", + "timeslider.toolbar.exportlink.title": "Изнасяне", + "timeslider.exportCurrent": "Изнасяне на текущата версия като:", + "timeslider.version": "Версия {{version}}", + "timeslider.month.january": "януари", + "timeslider.month.february": "февруари", + "timeslider.month.march": "март", + "timeslider.month.april": "април", + "timeslider.month.may": "май", + "timeslider.month.june": "юни", + "timeslider.month.july": "юли", + "timeslider.month.august": "август", + "timeslider.month.september": "септември", + "timeslider.month.october": "октомври", + "timeslider.month.november": "ноември", + "timeslider.month.december": "декември", + "pad.userlist.entername": "Въведете вашето име", + "pad.userlist.guest": "Гост" +} From 7029248a76a590e2f130bde71fe2bbfb2c032bbb Mon Sep 17 00:00:00 2001 From: Jan Holub Date: Wed, 21 Jun 2017 23:44:23 +0200 Subject: [PATCH 069/102] Added RobotoMono as a more modern and pretty monospaced font, addressing #3201 I added RobotoMono-Regular and RobotoMono-Bold as TrueTypeFont files and included them into the list. I tred to stay in alphabetical order where possible. The author of #3201 was asking for a more modern monospaced font. --- src/locales/en.json | 1 + src/static/css/pad.css | 17 +++++++++-- src/static/font/RobotoMono-Bold.ttf | Bin 0 -> 114752 bytes src/static/font/RobotoMono-Regular.ttf | Bin 0 -> 114624 bytes src/static/js/pad.js | 40 ++++++++++++------------- src/static/js/pad_editor.js | 7 +++-- src/templates/pad.html | 1 + 7 files changed, 41 insertions(+), 25 deletions(-) create mode 100755 src/static/font/RobotoMono-Bold.ttf create mode 100755 src/static/font/RobotoMono-Regular.ttf diff --git a/src/locales/en.json b/src/locales/en.json index 3e16c5de0..8aa5287e7 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -47,6 +47,7 @@ "pad.settings.fontType.lucida": "Lucida", "pad.settings.fontType.lucidasans": "Lucida Sans", "pad.settings.fontType.palatino": "Palatino", + "pad.settings.fontType.robotomono": "RobotoMono", "pad.settings.fontType.tahoma": "Tahoma", "pad.settings.fontType.timesnewroman": "Times New Roman", "pad.settings.fontType.trebuchet": "Trebuchet", diff --git a/src/static/css/pad.css b/src/static/css/pad.css index 5764c5e4a..ebe31bdef 100644 --- a/src/static/css/pad.css +++ b/src/static/css/pad.css @@ -1260,6 +1260,21 @@ input[type=checkbox] { src: url("../../static/font/opendyslexic.otf") format("opentype"); } +/* Roboto Mono */ +@font-face { + font-family: "RobotoMono"; + src: url("../../static/font/RobotoMono-Regular.ttf") format("truetype"); + font-weight: normal; + font-style: normal; +} +@font-face { + font-family: "RobotoMono"; + src: url("../../static/font/RobotoMono-Bold.ttf") format("truetype"); + font-weight: bold; + font-style: normal; +} +/* End of Roboto Mono */ + @font-face { font-family: "fontawesome-etherpad"; src:url("../../static/font/fontawesome-etherpad.eot"); @@ -1304,5 +1319,3 @@ input[type=checkbox] { .hideControlsEditbar{ display:none !important; } - - diff --git a/src/static/font/RobotoMono-Bold.ttf b/src/static/font/RobotoMono-Bold.ttf new file mode 100755 index 0000000000000000000000000000000000000000..07ef607d50c2e0b48d251910fc75c7eb83a41b34 GIT binary patch literal 114752 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
op0kl1RI-LWlRW`kzx#EleI9>7u9ev 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 vAbY)s5dY@ik>Xn8zCBFHb`EX^3h&Ilg9 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 literal 0 HcmV?d00001 diff --git a/src/static/js/pad.js b/src/static/js/pad.js index c967e4615..8208f5e47 100644 --- a/src/static/js/pad.js +++ b/src/static/js/pad.js @@ -1,5 +1,5 @@ /** - * This code is mostly from the old Etherpad. Please help us to comment this code. + * This code is mostly from the old Etherpad. Please help us to comment this code. * This helps other people to understand this code better and helps them to improve it. * TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED */ @@ -99,15 +99,15 @@ function getParams() setting.callback(value); } } - + // Then URL applied stuff var params = getUrlVars() - + for(var i = 0; i < getParameters.length; i++) { var setting = getParameters[i]; var value = params[setting.name]; - + if(value && (value == setting.checkVal || setting.checkVal == null)) { setting.callback(value); @@ -156,7 +156,7 @@ function sendClientReady(isReconnect, messageType) token = "t." + randomString(); createCookie("token", token, 60); } - + var sessionID = decodeURIComponent(readCookie("sessionID")); var password = readCookie("password"); @@ -169,14 +169,14 @@ function sendClientReady(isReconnect, messageType) "token": token, "protocolVersion": 2 }; - + //this is a reconnect, lets tell the server our revisionnumber if(isReconnect == true) { msg.client_rev=pad.collabClient.getCurrentRevisionNumber(); msg.reconnect=true; } - + socket.json.send(msg); } @@ -203,12 +203,12 @@ function handshake() socket.once('connect', function () { sendClientReady(false); }); - + socket.on('reconnect', function () { pad.collabClient.setChannelState("CONNECTED"); pad.sendClientReady(true); }); - + socket.on('reconnecting', function() { pad.collabClient.setChannelState("RECONNECTING"); }); @@ -254,7 +254,7 @@ function handshake() $("#passwordinput").focus(); } } - + //if we haven't recieved the clientVars yet, then this message should it be else if (!receivedClientVars && obj.type == "CLIENT_VARS") { @@ -267,7 +267,7 @@ function handshake() clientVars = obj.data; clientVars.userAgent = "Anonymous"; clientVars.collab_client_vars.clientAgent = "Anonymous"; - + //initalize the pad pad._afterHandshake(); initalized = true; @@ -298,7 +298,7 @@ function handshake() { pad.changeViewOption('noColors', true); } - + if (settings.rtlIsTrue == true) { pad.changeViewOption('rtlIsTrue', true); @@ -345,13 +345,13 @@ function handshake() }); // Bind the colorpicker var fb = $('#colorpicker').farbtastic({ callback: '#mycolorpickerpreview', width: 220}); - // Bind the read only button + // Bind the read only button $('#readonlyinput').on('click',function(){ padeditbar.setEmbedLinks(); }); } -$.extend($.gritter.options, { +$.extend($.gritter.options, { position: 'bottom-right', // defaults to 'top-right' but can be 'bottom-left', 'bottom-right', 'top-left', 'top-right' (added in 1.7.1) fade: false, // dont fade, too jerky on mobile time: 6000 // hang on the screen for... @@ -424,7 +424,7 @@ var pad = { if(window.history && window.history.pushState) { $('#chattext p').remove(); //clear the chat messages - window.history.pushState("", "", newHref); + window.history.pushState("", "", newHref); receivedClientVars = false; sendClientReady(false, 'SWITCH_TO_PAD'); } @@ -549,7 +549,7 @@ var pad = { } var fonts = ['useMonospaceFont', 'useOpenDyslexicFont', 'useComicSansFont', 'useCourierNewFont', 'useGeorgiaFont', 'useImpactFont', - 'useLucidaFont', 'useLucidaSansFont', 'usePalatinoFont', 'useTahomaFont', 'useTimesNewRomanFont', + 'useLucidaFont', 'useLucidaSansFont', 'usePalatinoFont', 'useRobotoMonoFont', 'useTahomaFont', 'useTimesNewRomanFont', 'useTrebuchetFont', 'useVerdanaFont', 'useSymbolFont', 'useWebdingsFont', 'useWingDingsFont', 'useSansSerifFont', 'useSerifFont']; @@ -731,20 +731,20 @@ var pad = { pad.diagnosticInfo.disconnectedMessage = message; pad.diagnosticInfo.padId = pad.getPadId(); pad.diagnosticInfo.socket = {}; - - //we filter non objects from the socket object and put them in the diagnosticInfo + + //we filter non objects from the socket object and put them in the diagnosticInfo //this ensures we have no cyclic data - this allows us to stringify the data for(var i in socket.socket) { var value = socket.socket[i]; var type = typeof value; - + if(type == "string" || type == "number") { pad.diagnosticInfo.socket[i] = value; } } - + pad.asyncSendDiagnosticInfo(); if (typeof window.ajlog == "string") { diff --git a/src/static/js/pad_editor.js b/src/static/js/pad_editor.js index 3e6b49d31..a1a901cb9 100644 --- a/src/static/js/pad_editor.js +++ b/src/static/js/pad_editor.js @@ -1,5 +1,5 @@ /** - * This code is mostly from the old Etherpad. Please help us to comment this code. + * This code is mostly from the old Etherpad. Please help us to comment this code. * This helps other people to understand this code better and helps them to improve it. * TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED */ @@ -31,7 +31,7 @@ var padeditor = (function() // Array of available fonts var fonts = ['useMonospaceFont', 'useOpenDyslexicFont', 'useComicSansFont', 'useCourierNewFont', 'useGeorgiaFont', 'useImpactFont', - 'useLucidaFont', 'useLucidaSansFont', 'usePalatinoFont', 'useTahomaFont', 'useTimesNewRomanFont', + 'useLucidaFont', 'useLucidaSansFont', 'usePalatinoFont', 'useRobotoMonoFont', 'useTahomaFont', 'useTimesNewRomanFont', 'useTrebuchetFont', 'useVerdanaFont', 'useSymbolFont', 'useWebdingsFont', 'useWingDingsFont', 'useSansSerifFont', 'useSerifFont']; @@ -102,7 +102,7 @@ var padeditor = (function() pad.changeViewOption(font, $("#viewfontmenu").val() == sfont); }); }); - + // Language html10n.bind('localized', function() { $("#languagemenu").val(html10n.getLanguage()); @@ -168,6 +168,7 @@ var padeditor = (function() if(font === "lucida") self.ace.setProperty("textface", "Lucida,'Lucida Serif','Lucida Bright',serif"); if(font === "lucidasans") self.ace.setProperty("textface", "'Lucida Sans','Lucida Grande','Lucida Sans Unicode','Luxi Sans',sans-serif"); if(font === "palatino") self.ace.setProperty("textface", "Palatino,'Palatino Linotype','URW Palladio L',Georgia,serif"); + if(font === "robotomono") self.ace.setProperty("textface", "RobotoMono"); if(font === "tahoma") self.ace.setProperty("textface", "Tahoma,sans-serif"); if(font === "timesnewroman") self.ace.setProperty("textface", "'Times New Roman',Times,serif"); if(font === "trebuchet") self.ace.setProperty("textface", "'Trebuchet MS',sans-serif"); diff --git a/src/templates/pad.html b/src/templates/pad.html index 3d89f9d07..6613f6111 100644 --- a/src/templates/pad.html +++ b/src/templates/pad.html @@ -168,6 +168,7 @@ + From 7b4f672b79ff1e4df5bb4b0b55a5810da670b594 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 26 Jun 2017 09:07:27 +0200 Subject: [PATCH 070/102] Localisation updates from https://translatewiki.net. --- src/locales/eu.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/locales/eu.json b/src/locales/eu.json index 4ef451857..0d5e232ae 100644 --- a/src/locales/eu.json +++ b/src/locales/eu.json @@ -4,7 +4,8 @@ "Theklan", "Subi", "Xabier Armendaritz", - "An13sa" + "An13sa", + "Mikel Ibaiba" ] }, "index.newPad": "Pad berria", @@ -59,6 +60,7 @@ "pad.modals.connected": "Konektatuta.", "pad.modals.reconnecting": "Zure pad-era birkonektatu...", "pad.modals.forcereconnect": "Berkonexioa fortzatu", + "pad.modals.cancel": "Deuseztatu", "pad.modals.userdup": "Beste leiho batean ireki da", "pad.modals.userdup.explanation": "Pad hau zure nabigatzailearen beste leiho batean irekita dagoela ematen du.", "pad.modals.userdup.advice": "Berriro konektatu beste leiho hau erabiltzeko.", From b2ba0625f7d8fb0b947b7b5ca5dccf32caf554b6 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 3 Jul 2017 07:35:44 +0200 Subject: [PATCH 071/102] Localisation updates from https://translatewiki.net. --- src/locales/pt-br.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/locales/pt-br.json b/src/locales/pt-br.json index e356041f6..d72a71289 100644 --- a/src/locales/pt-br.json +++ b/src/locales/pt-br.json @@ -15,7 +15,8 @@ "Fasouzafreitas", "Lpagliari", "Walesson", - "Cainamarques" + "Cainamarques", + "Eduardo Addad de Oliveira" ] }, "index.newPad": "Nova Nota", @@ -70,6 +71,8 @@ "pad.modals.connected": "Conectado.", "pad.modals.reconnecting": "Reconectando à sua nota...", "pad.modals.forcereconnect": "Forçar reconexão", + "pad.modals.reconnecttimer": "Tentando se reconectar", + "pad.modals.cancel": "Cancelar", "pad.modals.userdup": "Aberto em outra janela", "pad.modals.userdup.explanation": "Esta nota parece estar aberta em mais de uma janela de navegador deste computador.", "pad.modals.userdup.advice": "Reconectar para usar esta janela.", From 12cb8e0dc1ba56ede302ed328d689a370334746a Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Tue, 4 Jul 2017 10:04:28 +0200 Subject: [PATCH 072/102] Localisation updates from https://translatewiki.net. --- src/locales/ar.json | 4 +++- src/locales/ca.json | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/locales/ar.json b/src/locales/ar.json index 914eb9942..39ec236ce 100644 --- a/src/locales/ar.json +++ b/src/locales/ar.json @@ -9,7 +9,8 @@ "محمد أحمد عبد الفتاح", "Haytham morsy", "ديفيد", - "Mido" + "Mido", + "Shbib Al-Subaie" ] }, "index.newPad": "باد جديد", @@ -64,6 +65,7 @@ "pad.modals.connected": "متصل.", "pad.modals.reconnecting": "إعادة الاتصال ببادك", "pad.modals.forcereconnect": "فرض إعادة الاتصال", + "pad.modals.reconnecttimer": "حاول إعادة الاتصال", "pad.modals.cancel": "إلغاء", "pad.modals.userdup": "مفتوح في نافذة أخرى", "pad.modals.userdup.explanation": "يبدو أن هذا الباد تم فتحه في أكثر من نافذة متصفح في هذا الحاسوب.", diff --git a/src/locales/ca.json b/src/locales/ca.json index 40a833d06..714306106 100644 --- a/src/locales/ca.json +++ b/src/locales/ca.json @@ -8,7 +8,8 @@ "Macofe", "Joan manel", "Eduardo Martinez", - "Jaumeortola" + "Jaumeortola", + "Ssola" ] }, "index.newPad": "Nou pad", @@ -63,6 +64,8 @@ "pad.modals.connected": "Connectat.", "pad.modals.reconnecting": "S'està tornant a connectar al vostre pad…", "pad.modals.forcereconnect": "Força tornar a connectar", + "pad.modals.reconnecttimer": "Intentant reconnectar en", + "pad.modals.cancel": "Cancel·la", "pad.modals.userdup": "Obert en una altra finestra", "pad.modals.userdup.explanation": "Aquest pad sembla que està obert en més d'una finestra de navegador de l'ordinador.", "pad.modals.userdup.advice": "Torneu a connectar-vos per a utilitzar aquesta finestra.", From d72d79ea82301dbc5ac575d0e0d0726f91a17b60 Mon Sep 17 00:00:00 2001 From: Patrick Easters Date: Wed, 5 Jul 2017 15:20:02 -0400 Subject: [PATCH 073/102] Fetch credentials arg from CLI --- src/node/utils/Cli.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/node/utils/Cli.js b/src/node/utils/Cli.js index 0c7947e91..9419ed26b 100644 --- a/src/node/utils/Cli.js +++ b/src/node/utils/Cli.js @@ -34,5 +34,10 @@ for ( var i = 0; i < argv.length; i++ ) { exports.argv.settings = arg; } + // Override location of credentials.json file + if ( prevArg == '--credentials' ) { + exports.argv.credentials = arg; + } + prevArg = arg; } From f9203524a4db9de58e8d37eca424a9efbdb6ac1b Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 6 Jul 2017 11:10:08 +0200 Subject: [PATCH 074/102] Localisation updates from https://translatewiki.net. --- src/locales/eu.json | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/locales/eu.json b/src/locales/eu.json index 0d5e232ae..ac7fab2f6 100644 --- a/src/locales/eu.json +++ b/src/locales/eu.json @@ -60,6 +60,7 @@ "pad.modals.connected": "Konektatuta.", "pad.modals.reconnecting": "Zure pad-era birkonektatu...", "pad.modals.forcereconnect": "Berkonexioa fortzatu", + "pad.modals.reconnecttimer": "Berriz konektatzen saiatzen", "pad.modals.cancel": "Deuseztatu", "pad.modals.userdup": "Beste leiho batean ireki da", "pad.modals.userdup.explanation": "Pad hau zure nabigatzailearen beste leiho batean irekita dagoela ematen du.", @@ -74,6 +75,9 @@ "pad.modals.slowcommit.explanation": "Zerbitzariak ez du erantzuten.", "pad.modals.slowcommit.cause": "Baliteke hau sarearen konexio arazoak direla eta izatea.", "pad.modals.badChangeset.explanation": "Sinkronizazio zerbitzariak, zuk egindako aldaketa bat legez kanpokotzat jo du.", + "pad.modals.badChangeset.cause": "Honek zerbitzariaren konfigurazio okerra edo ustekabeko beste jokabidearen baten ondorio izan liteke. Jarri harremanetan zerbitzu-administratzailearekin, errore bat dela uste baduzu. Saiatu berriro konektatzen edizioarekin jarraitzeko.", + "pad.modals.corruptPad.explanation": "Sartzen saiatzen ari zaren Pad-a hondatuta dago.", + "pad.modals.corruptPad.cause": "Baliteke zerbitzari okerreko konfigurazioa edo beste ustekabeko portaera batzuk izatea. Jarri harremanetan zerbitzu-administratzailearekin.", "pad.modals.deleted": "Ezabatua.", "pad.modals.deleted.explanation": "Pad hau ezabatua izan da.", "pad.modals.disconnected": "Deskonektatua izan zara.", @@ -94,6 +98,9 @@ "timeslider.exportCurrent": "Gorde bertsio hau honela:", "timeslider.version": "Bertsioa {{version}}", "timeslider.saved": "{{year}}ko {{month}}ren {{day}}an gordeta", + "timeslider.playPause": "Berriro erreproduzitu / gelditu Pad edukiak", + "timeslider.backRevision": "Berrikusketa bat atzerago joan Pad honetan", + "timeslider.forwardRevision": "Berrikusketa bat aurrerago joan Pad honetan", "timeslider.dateformat": "{{year}}-{{month}}-{{day}} {{hours}}:{{minutes}}:{{seconds}}", "timeslider.month.january": "Urtarrila", "timeslider.month.february": "Otsaila", @@ -109,6 +116,7 @@ "timeslider.month.december": "Abendua", "timeslider.unnamedauthors": "{{num}} izenik gabeko {[plural(num) one: egilea, other: egileak]}", "pad.savedrevs.marked": "Berrikuspen hau markatua dago gordetako berrikuspen gisa", + "pad.savedrevs.timeslider": "Gordetako berrikusketak ikus ditzakezu denbora-graduatzailea bisitatuz", "pad.userlist.entername": "Sartu zure erabiltzaile izena", "pad.userlist.unnamed": "izenik gabe", "pad.userlist.guest": "Gonbidatua", @@ -119,6 +127,7 @@ "pad.impexp.importing": "Inportatzen...", "pad.impexp.confirmimport": "Fitxategi bat inportatzen baduzu oraingo pad honen testua ezabatuko da. Ziur zaude jarraitu nahi duzula?", "pad.impexp.convertFailed": "Ez gara gai fitxategi hau inportatzeko. Erabil ezazu, mesedez, beste dokumentu formatu bat edo kopiatu eta itsasi eskuz.", + "pad.impexp.padHasData": "Artxibo hau ezin izan dugu inportatu Pad hau aldaketak izan dituelako jada, Pad berria inportatu mesedez.", "pad.impexp.uploadFailed": "Igotzean akatsa egon da, saia zaitez berriro", "pad.impexp.importfailed": "Inportazioak akatsa egin du", "pad.impexp.copypaste": "Mesedez kopiatu eta pegatu", From 2508b9749ce040237ce8f89b60118ab108084baf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Biel?= Date: Mon, 10 Jul 2017 20:59:08 +0200 Subject: [PATCH 075/102] fix typo --- src/node/db/SecurityManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node/db/SecurityManager.js b/src/node/db/SecurityManager.js index 6fae57ffb..bbd8cef49 100644 --- a/src/node/db/SecurityManager.js +++ b/src/node/db/SecurityManager.js @@ -31,7 +31,7 @@ var authLogger = log4js.getLogger("auth"); /** * This function controlls the access to a pad, it checks if the user can access a pad. * @param padID the pad the user wants to access - * @param sesssionID the session the user has (set via api) + * @param sessionCookie the session the user has (set via api) * @param token the token of the author (randomly generated at client side, used for public pads) * @param password the password the user has given to access this pad, can be null * @param callback will be called with (err, {accessStatus: grant|deny|wrongPassword|needPassword, authorID: a.xxxxxx}) From 8bd8be97b98a69dce9768e5717c4f5ee0368ad1a Mon Sep 17 00:00:00 2001 From: Jan Holub Date: Wed, 12 Jul 2017 17:21:48 +0200 Subject: [PATCH 076/102] Added support for the Montserrat Font as discussed in #3201 (#3205) * Added support for the Montserrat Font as discussed in #3201 I chose a thin version of the Font (namely Montserrat Light) as the regular font and Montserrat Regular as the bold version. The thin fonts just look better in my opinion. --- src/locales/en.json | 1 + src/static/css/pad.css | 15 +++++++++++++++ src/static/font/Montserrat-Light.otf | Bin 0 -> 91496 bytes src/static/font/Montserrat-Regular.otf | Bin 0 -> 93516 bytes src/static/js/pad.js | 10 ++++++---- src/static/js/pad_editor.js | 11 +++++++---- src/templates/pad.html | 1 + 7 files changed, 30 insertions(+), 8 deletions(-) create mode 100755 src/static/font/Montserrat-Light.otf create mode 100755 src/static/font/Montserrat-Regular.otf diff --git a/src/locales/en.json b/src/locales/en.json index b9c8cb74e..116f21690 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -40,6 +40,7 @@ "pad.settings.fontType.normal": "Normal", "pad.settings.fontType.opendyslexic": "Open Dyslexic", "pad.settings.fontType.monospaced": "Monospace", + "pad.settings.fontType.montserrat": "Montserrat", "pad.settings.fontType.comicsans": "Comic Sans", "pad.settings.fontType.couriernew": "Courier New", "pad.settings.fontType.georgia": "Georgia", diff --git a/src/static/css/pad.css b/src/static/css/pad.css index 397e61eea..cabde7ef2 100644 --- a/src/static/css/pad.css +++ b/src/static/css/pad.css @@ -1272,6 +1272,21 @@ input[type=checkbox] { } /* End of gritter stuff */ +/* Montserrat Font */ +@font-face { + font-family: "Montserrat"; + src: url("../../static/font/Montserrat-Light.otf") format("opentype"); + font-weight: normal; + font-style: normal; +} +@font-face { + font-family: "Montserrat"; + src: url("../../static/font/Montserrat-Regular.otf") format("opentype"); + font-weight: bold; + font-style: normal; +} +/* End of Monterrat Font */ + @font-face { font-family: opendyslexic; src: url("../../static/font/opendyslexic.otf") format("opentype"); diff --git a/src/static/font/Montserrat-Light.otf b/src/static/font/Montserrat-Light.otf new file mode 100755 index 0000000000000000000000000000000000000000..f2f0e2df0899bec6f9307d5030b94ad1b05dd12f GIT binary patch literal 91496 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