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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 literal 0 HcmV?d00001 diff --git a/src/static/font/RobotoMono-Regular.ttf b/src/static/font/RobotoMono-Regular.ttf new file mode 100755 index 0000000000000000000000000000000000000000..b158a334eb372a9ab2ecd4f2566e60d561e71a9f GIT binary patch literal 114624 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

WH`00`s@p7bm8Ow12>ck9v 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 + 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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 + From cdaee77a7677ab8fd90b68d2b2a37ad9c522214f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matic=20Poto=C4=8Dnik?= Date: Thu, 27 Jul 2017 02:42:42 +0200 Subject: [PATCH 077/102] Fix AbiWord wikilink and capitalization (#3227) --- src/locales/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/locales/en.json b/src/locales/en.json index 116f21690..e438fa1b4 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -71,7 +71,7 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "You only can import from plain text or HTML formats. For more advanced import features please install abiword.", + "pad.importExport.abiword.innerHTML": "You only can import from plain text or HTML formats. For more advanced import features please install AbiWord.", "pad.modals.connected": "Connected.", "pad.modals.reconnecting": "Reconnecting to your pad..", From 65fc8d830b3f9064c100c7d634888beab2ea5ca0 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 27 Jul 2017 10:10:28 +0200 Subject: [PATCH 078/102] Localisation updates from https://translatewiki.net. --- src/locales/de.json | 2 +- src/locales/ms.json | 5 +++-- src/locales/sl.json | 5 ++++- src/locales/zh-hans.json | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/locales/de.json b/src/locales/de.json index c4ac315ce..85bd3bfff 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -58,7 +58,7 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Sie können nur aus reinen Text- oder HTML-Formaten importieren. Für umfangreichere Importfunktionen installieren Sie bitte abiword.", + "pad.importExport.abiword.innerHTML": "Sie können nur aus reinen Text- oder HTML-Formaten importieren. Für umfangreichere Importfunktionen installieren Sie bitte AbiWord.", "pad.modals.connected": "Verbunden.", "pad.modals.reconnecting": "Wiederherstellen der Verbindung …", "pad.modals.forcereconnect": "Erneutes Verbinden erzwingen", diff --git a/src/locales/ms.json b/src/locales/ms.json index 93b421faf..e23fa30a6 100644 --- a/src/locales/ms.json +++ b/src/locales/ms.json @@ -1,7 +1,8 @@ { "@metadata": { "authors": [ - "Anakmalaysia" + "Anakmalaysia", + "Jeluang Terluang" ] }, "index.newPad": "Pad baru", @@ -69,7 +70,7 @@ "pad.modals.slowcommit.explanation": "Pelayan tidak membalas.", "pad.modals.slowcommit.cause": "Ini mungkin disebabkan oleh masalah dengan kesambungan rangkaian anda.", "pad.modals.badChangeset.explanation": "Suntingan yang telah anda lakukan telah dikira sebagai terlarang oleh pelayan penyegerakan.", - "pad.modals.badChangeset.cause": "Ini mungkin disebabkan oleh konfigurasi pelayan salah atau sesuatu kelakuan yang tidak dijangka. Sila hubungi penyelia servis anda jika anda merasakan ini adalah satu kesilapan. Cuba sambungkan semula talian untuk terus menyuntung.", + "pad.modals.badChangeset.cause": "Hal ini mungkin disebabkan oleh konfigurasi pelayan salah atau sesuatu kelakuan yang tidak dijangka. Sila hubungi penyelia servis anda jika anda merasakan ini ialah satu kesilapan. Cuba sambungkan semula talian untuk terus menyunting.", "pad.modals.corruptPad.explanation": "Pad yang anda cuba akses itu telah tercemar.", "pad.modals.corruptPad.cause": "Ini mungkin disebabkan oleh konfigurasi pelayan salah atau sesuatu kelakuan yang tidak dijangka. Sila hubungi penyelia servis anda.", "pad.modals.deleted": "Dihapuskan.", diff --git a/src/locales/sl.json b/src/locales/sl.json index 5d2dd85ee..6748ac8d4 100644 --- a/src/locales/sl.json +++ b/src/locales/sl.json @@ -3,7 +3,8 @@ "authors": [ "Dbc334", "Mateju", - "Skalcaa" + "Skalcaa", + "HairyFotr" ] }, "index.newPad": "Nov dokument", @@ -58,6 +59,8 @@ "pad.modals.connected": "Povezano.", "pad.modals.reconnecting": "Poteka povezovanje z dokumentom ...", "pad.modals.forcereconnect": "Vsili ponovno povezavo.", + "pad.modals.reconnecttimer": "Poskus ponovne vzpostavitve povezave čez", + "pad.modals.cancel": "Prekliči", "pad.modals.userdup": "Dokument je že odprt v v drugem oknu.", "pad.modals.userdup.explanation": "Videti je, da je ta dokument odprt v več kot enem oknu brskalnika na tem računalniku.", "pad.modals.userdup.advice": "Ponovno vzpostavite povezavo in uporabljajte to okno.", diff --git a/src/locales/zh-hans.json b/src/locales/zh-hans.json index 08d33053c..a598d9aad 100644 --- a/src/locales/zh-hans.json +++ b/src/locales/zh-hans.json @@ -62,7 +62,7 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF(开放文档格式)", - "pad.importExport.abiword.innerHTML": "您只能导入纯文本或HTML格式。安裝abiword取得更多高级的导入功能。", + "pad.importExport.abiword.innerHTML": "您只可以导入纯文本或HTML格式。要获取更高级的导入功能,请安装AbiWord。", "pad.modals.connected": "已连接。", "pad.modals.reconnecting": "重新连接到您的记事本...", "pad.modals.forcereconnect": "强制重新连接", From 59ba183c82eb3bbbe2da12df2d562c44f6798711 Mon Sep 17 00:00:00 2001 From: Robert Helmer Date: Thu, 27 Jul 2017 13:41:18 -0700 Subject: [PATCH 079/102] Issue #2948 - disable sauce labs frontend tests until they are working. (#3230) --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 911ea8bad..908aca419 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,8 +5,6 @@ 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: - "tests/frontend/travis/runner.sh" env: From e4ddb42e11d9026199be4fcc37360082a48bee1c Mon Sep 17 00:00:00 2001 From: Jainendra Mandavi Date: Fri, 28 Jul 2017 18:28:23 +0530 Subject: [PATCH 080/102] FIX-2864: Add useAbiword flag This is a fix for the issue - 2864 Which is import failure of PDF after importing a text file --- src/node/handler/ImportHandler.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/node/handler/ImportHandler.js b/src/node/handler/ImportHandler.js index 870c954aa..6aa94e649 100644 --- a/src/node/handler/ImportHandler.js +++ b/src/node/handler/ImportHandler.js @@ -56,10 +56,14 @@ exports.doImport = function(req, res, padId) , pad , text , importHandledByPlugin - , directDatabaseAccess; + , directDatabaseAccess + , useAbiword; var randNum = Math.floor(Math.random()*0xFFFFFFFF); + // setting flag for whether to use abiword or not + useAbiword = (abiword != null); + async.series([ //save the uploaded file to /tmp function(callback) { @@ -147,9 +151,9 @@ exports.doImport = function(req, res, padId) var fileEnding = path.extname(srcFile).toLowerCase(); var fileIsHTML = (fileEnding === ".html" || fileEnding === ".htm"); var fileIsTXT = (fileEnding === ".txt"); - if (fileIsTXT) abiword = false; // Don't use abiword for text files + if (fileIsTXT) useAbiword = false; // Don't use abiword for text files // See https://github.com/ether/etherpad-lite/issues/2572 - if (abiword && !fileIsHTML) { + if (useAbiword && !fileIsHTML) { abiword.convertFile(srcFile, destFile, "htm", function(err) { //catch convert errors if(err) { @@ -169,7 +173,7 @@ exports.doImport = function(req, res, padId) }, function(callback) { - if (!abiword && !directDatabaseAccess){ + if (!useAbiword && !directDatabaseAccess){ // Read the file with no encoding for raw buffer access. fs.readFile(destFile, function(err, buf) { if (err) throw err; @@ -228,7 +232,7 @@ exports.doImport = function(req, res, padId) function(callback) { if(!directDatabaseAccess){ var fileEnding = path.extname(srcFile).toLowerCase(); - if (importHandledByPlugin || abiword || fileEnding == ".htm" || fileEnding == ".html") { + if (importHandledByPlugin || useAbiword || fileEnding == ".htm" || fileEnding == ".html") { importHtml.setPadHTML(pad, text, function(e){ if(e) apiLogger.warn("Error importing, possibly caused by malformed HTML"); }); From 67c4e336e0892c75c207214fb631e4b41768e14f Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 31 Jul 2017 14:58:13 +0200 Subject: [PATCH 081/102] Localisation updates from https://translatewiki.net. --- src/locales/be-tarask.json | 2 +- src/locales/cs.json | 5 +- src/locales/en-gb.json | 5 +- src/locales/es.json | 2 +- src/locales/eu.json | 5 +- src/locales/fr.json | 2 +- src/locales/he.json | 2 +- src/locales/kab.json | 129 +++++++++++++++++++++++++++++++++++++ src/locales/ko.json | 21 +++--- src/locales/sl.json | 72 ++++++++++----------- src/locales/sv.json | 2 +- 11 files changed, 190 insertions(+), 57 deletions(-) create mode 100644 src/locales/kab.json diff --git a/src/locales/be-tarask.json b/src/locales/be-tarask.json index e9421ada2..84af73156 100644 --- a/src/locales/be-tarask.json +++ b/src/locales/be-tarask.json @@ -54,7 +54,7 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Вы можаце імпартаваць толькі з звычайнага тэксту або HTML. Дзеля больш пашыраных магчымасьцяў імпарту, калі ласка, усталюйце abiword.", + "pad.importExport.abiword.innerHTML": "Вы можаце імпартаваць толькі з звычайнага тэксту або HTML. Дзеля больш пашыраных магчымасьцяў імпарту, калі ласка, усталюйце AbiWord.", "pad.modals.connected": "Падлучыліся.", "pad.modals.reconnecting": "Перападлучэньне да вашага дакумэнта...", "pad.modals.forcereconnect": "Прымусовае перападлучэньне", diff --git a/src/locales/cs.json b/src/locales/cs.json index cc537de7f..cda8ccb08 100644 --- a/src/locales/cs.json +++ b/src/locales/cs.json @@ -7,7 +7,8 @@ "Leanes", "Quinn", "Aktron", - "Mormegil" + "Mormegil", + "Dvorapa" ] }, "index.newPad": "Založ nový Pad", @@ -58,7 +59,7 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Importovat můžeš pouze prostý text nebo HTML formátování. Pro pokročilejší funkce importu, prosím, nainstaluj „abiword“.", + "pad.importExport.abiword.innerHTML": "Importovat můžeš pouze prostý text nebo HTML formátování. Pro pokročilejší funkce importu, prosím, nainstaluj „AbiWord“.", "pad.modals.connected": "Připojeno.", "pad.modals.reconnecting": "Znovupřipojování k Padu…", "pad.modals.forcereconnect": "Vynutit znovupřipojení", diff --git a/src/locales/en-gb.json b/src/locales/en-gb.json index c3746f9be..6206f7736 100644 --- a/src/locales/en-gb.json +++ b/src/locales/en-gb.json @@ -3,7 +3,8 @@ "authors": [ "Chase me ladies, I'm the Cavalry", "Shirayuki", - "Andibing" + "Andibing", + "HairyFotr" ] }, "index.newPad": "New Pad", @@ -54,7 +55,7 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "You only can import from plain text or HTML formats. For more advanced import features please install abiword.", + "pad.importExport.abiword.innerHTML": "You only can import from plain text or HTML formats. For more advanced import features please install AbiWord.", "pad.modals.connected": "Connected.", "pad.modals.reconnecting": "Reconnecting to your pad..", "pad.modals.forcereconnect": "Force reconnect", diff --git a/src/locales/es.json b/src/locales/es.json index 8053436f7..321f15491 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -64,7 +64,7 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Solo es posible importar texto sin formato o en HTML. Para obtener funciones de importación más avanzadas es necesario instalar AbiWord.", + "pad.importExport.abiword.innerHTML": "Solo es posible importar texto sin formato o en HTML. Para obtener funciones de importación más avanzadas es necesario instalar AbiWord.", "pad.modals.connected": "Conectado.", "pad.modals.reconnecting": "Reconectando a tu pad..", "pad.modals.forcereconnect": "Forzar reconexión", diff --git a/src/locales/eu.json b/src/locales/eu.json index ac7fab2f6..fd6c39504 100644 --- a/src/locales/eu.json +++ b/src/locales/eu.json @@ -5,7 +5,8 @@ "Subi", "Xabier Armendaritz", "An13sa", - "Mikel Ibaiba" + "Mikel Ibaiba", + "HairyFotr" ] }, "index.newPad": "Pad berria", @@ -56,7 +57,7 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Testu laua edo html formatudun testuak bakarrik inporta ditzakezu. Aurreratuagoak diren inportazio aukerak izateko abiword instala ezazu.", + "pad.importExport.abiword.innerHTML": "Testu laua edo HTML formatudun testuak bakarrik inporta ditzakezu. Aurreratuagoak diren inportazio aukerak izateko AbiWord instala ezazu.", "pad.modals.connected": "Konektatuta.", "pad.modals.reconnecting": "Zure pad-era birkonektatu...", "pad.modals.forcereconnect": "Berkonexioa fortzatu", diff --git a/src/locales/fr.json b/src/locales/fr.json index 4213e3460..5f6b664a8 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -74,7 +74,7 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Vous ne pouvez importer que des formats texte brut ou HTML. Pour des fonctionnalités d'importation plus évoluées, veuillez installer Abiword.", + "pad.importExport.abiword.innerHTML": "Vous ne pouvez importer que des formats texte brut ou HTML. Pour des fonctionnalités d'importation plus évoluées, veuillez installer AbiWord.", "pad.modals.connected": "Connecté.", "pad.modals.reconnecting": "Reconnexion vers votre pad...", "pad.modals.forcereconnect": "Forcer la reconnexion", diff --git a/src/locales/he.json b/src/locales/he.json index 25dd026eb..a857671da 100644 --- a/src/locales/he.json +++ b/src/locales/he.json @@ -55,7 +55,7 @@ "pad.importExport.exportword": "מיקרוסופט וורד", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "באפשרותך לייבא מטקסט פשוט או מ־HTML. לאפשרויות ייבוא מתקדמות יותר יש להתקין את abiword.", + "pad.importExport.abiword.innerHTML": "באפשרותך לייבא מטקסט פשוט או מ־HTML. לאפשרויות ייבוא מתקדמות יותר יש להתקין AbiWord.", "pad.modals.connected": "מחובר.", "pad.modals.reconnecting": "מתבצע חיבור מחדש...", "pad.modals.forcereconnect": "לכפות חיבור מחדש", diff --git a/src/locales/kab.json b/src/locales/kab.json new file mode 100644 index 000000000..905c38558 --- /dev/null +++ b/src/locales/kab.json @@ -0,0 +1,129 @@ +{ + "@metadata": { + "authors": [ + "Belkacem77" + ] + }, + "index.newPad": "Apad amaynut", + "index.createOpenPad": "neɣ rnu/ldi apad s yisem:", + "pad.toolbar.bold.title": "Zur (Ctrl+B)", + "pad.toolbar.italic.title": "Uknan (Ctrl+I)", + "pad.toolbar.underline.title": "Ituderrer (Ctrl+U)", + "pad.toolbar.strikethrough.title": "Ittujerreḍ (Ctrl+5)", + "pad.toolbar.ol.title": "Tabdart n usmizzwer (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Tabdart s war asmizzwer (Ctrl+Shift+L)", + "pad.toolbar.indent.title": "Rigel (TAB)", + "pad.toolbar.unindent.title": "Kkes ariger (Shift+TAB)", + "pad.toolbar.undo.title": "Sefsex (Ctrl+Z)", + "pad.toolbar.redo.title": "Err-d (Ctrl+Y)", + "pad.toolbar.clearAuthorship.title": "Sfeḍ initen yemmalen imeskaren (Ctrl+Shift+C)", + "pad.toolbar.import_export.title": "Kter/Sifeḍ seg/ɣer umasal n ufaylu-nnḍen", + "pad.toolbar.timeslider.title": "Amazray asmussan", + "pad.toolbar.savedRevision.title": "Sekles aceggir", + "pad.toolbar.settings.title": "Iɣewwaṛen", + "pad.toolbar.embed.title": "Bḍu sakin seddu apad-agi", + "pad.toolbar.showusers.title": "Sken iseqdacen ɣef upad-agi", + "pad.colorpicker.save": "Sekles", + "pad.colorpicker.cancel": "Sefsex", + "pad.loading": "Asali...", + "pad.noCookie": "Anagi n tuqqna ulac-it. Sireg inagan n tuqqna deg iminig-ik!", + "pad.passwordRequired": "Tesriḍ awal uffir akken ad tkecmeḍ ar upad-agi", + "pad.permissionDenied": "Ur ɣur-k ara tasiregt akken ad tkecmeḍ ar upad-agi", + "pad.wrongPassword": "Awal-uhhir mačči d ameɣtu", + "pad.settings.padSettings": "Iɣewwaṛen n upad", + "pad.settings.myView": "Timeẓri-iw", + "pad.settings.stickychat": "Asqerdec yezga deg ugdil", + "pad.settings.chatandusers": "Sken asqerdec akken iseqdacen", + "pad.settings.colorcheck": "Initen n usulu", + "pad.settings.linenocheck": "Uṭṭunen n izirigen", + "pad.settings.rtlcheck": "Ɣeṛ agbur seg uyeffus s azelmaḍ?", + "pad.settings.fontType": "Anaw n tsefsit:", + "pad.settings.globalView": "Timeẓri tamatut:", + "pad.settings.language": "Tutlayt:", + "pad.importExport.import_export": "Kter/Sifeḍ", + "pad.importExport.import": "Sali aḍris neɣ isemli", + "pad.importExport.importSuccessful": "Yedda!", + "pad.importExport.export": "Sifeḍ apad amiran am:", + "pad.importExport.exportetherpad": "Etherpad", + "pad.importExport.exporthtml": "HTML", + "pad.importExport.exportplain": "Adris aččuran", + "pad.importExport.exportword": "Microsoft Word", + "pad.importExport.exportpdf": "PDF", + "pad.importExport.exportopen": "ODF (Open Document Format)", + "pad.importExport.abiword.innerHTML": "Tzemreḍ kan ad ketreḍ aḍris aččuran neɣ imasalen HTML. Ugar n tmahilin n ukter leqqayen, rzu ar Sebded AbiWord.", + "pad.modals.connected": "Iqqen.", + "pad.modals.reconnecting": "Tulsa n tuqqna ar upad-ik.", + "pad.modals.forcereconnect": "Ḥettem tulsa n tuqqna", + "pad.modals.reconnecttimer": "Ɛreḍ tikelt-nniḍen tuqqna", + "pad.modals.cancel": "Sefsex", + "pad.modals.userdup": "Yeldi deg usfaylu-nniḍen", + "pad.modals.userdup.explanation": "Apad-agi yettban yeldi deg isfuyla-nniḍen deg uselkim-agi.", + "pad.modals.userdup.advice": "Ales tuqqna akken ad tesqedceḍ asfaylu-agi.", + "pad.modals.unauth": "Ur uettwasireg ara", + "pad.modals.unauth.explanation": "Tisirag-ik beddlent makken ad d-yettwaskan usebter. Ɛreḍ ad teqqneḍ.", + "pad.modals.looping.explanation": "Nufa-d uguren n teywalt akked uqeddac n umtawi.", + "pad.modals.looping.cause": "Ahat teqqneḍ s uɣrab n tmes neɣ apṛuksi ur yemṣadan ara", + "pad.modals.initsocketfail": "Ulac aqeddac.", + "pad.modals.initsocketfail.explanation": "Ur izmir ara ad yeqqen ar uqeddac n umtawi.", + "pad.modals.initsocketfail.cause": "Ahat d ugur i d-yekkan seg iminig-ik neɣ tuqqna ar Internet.", + "pad.modals.slowcommit.explanation": "Aqeddac ur d-yettara ara awal.", + "pad.modals.slowcommit.cause": "Ahat d ugur i d-yekkan seg tuqqna ar uẓeṭṭa.", + "pad.modals.badChangeset.explanation": "Abeddel i tgiḍ yettwammel d ayen ur ilaqen ara deg uqeddac n umtawi.", + "pad.modals.badChangeset.cause": "Ahat ayagi yekka-d si yir tawila n uqeddac neɣ kra n wayen ur nerǧi ara. Nermes anebdal n umeẓlu, ma yella tḥulfaḍ d tuccḍa. Ɛreḍ tuqqna akken ad tkemmleḍ taẓrigt.", + "pad.modals.corruptPad.explanation": "Apad i tettaɣraḍeḍ ad tkecmeḍ yexseṛ.", + "pad.modals.corruptPad.cause": "Ayagi ahat yekka-d seg yir tawila n uqeddac neɣ ayen ur yettwaṛǧan ara. Nermes anebdal n umeẓlu.", + "pad.modals.deleted": "Yettwakkes.", + "pad.modals.deleted.explanation": "Apad-agi yettwakkes.", + "pad.modals.disconnected": "Suffren-k.", + "pad.modals.disconnected.explanation": "Tuqqna ar uqeddac truḥ", + "pad.modals.disconnected.cause": "Ahat aqeddac ulac-it. Nermes anebdal n umeẓlu ma yella yezga iḍeṛṛu", + "pad.share": "Bḍu apad-agi", + "pad.share.readonly": "Taɣuri kan", + "pad.share.link": "Aseɣwen", + "pad.share.emebdcode": "Seddu URL", + "pad.chat": "Asqerdec", + "pad.chat.title": "Ldi asqerdec deg upad-agi.", + "pad.chat.loadmessages": "Sali-d ugar n yiznan", + "timeslider.pageTitle": "Amazray asmussan n {{appTitle}}", + "timeslider.toolbar.returnbutton": "Uqal ar upad", + "timeslider.toolbar.authors": "Imeskaren:", + "timeslider.toolbar.authorsList": "Ulac imeskaren", + "timeslider.toolbar.exportlink.title": "Sifeḍ", + "timeslider.exportCurrent": "Sifeḍ lqem-agi amiran am:", + "timeslider.version": "Lqem {{version}}", + "timeslider.saved": "Yettwasekles deg {{day}}-{{month}}-{{year}}", + "timeslider.playPause": "Taɣuri/Aserǧu n igburen n upad", + "timeslider.backRevision": "Uɣal s yiwen n uceggir ar deffir deg upad-agi", + "timeslider.forwardRevision": "Ddu ar zdat s yiwen n uceggir deg upad-agi", + "timeslider.dateformat": "{{day}}-{{month}}-{{year}} {{hours}}:{{minutes}}:{{seconds}}", + "timeslider.month.january": "Yennayer", + "timeslider.month.february": "Fuṛaṛ", + "timeslider.month.march": "Meɣres", + "timeslider.month.april": "Yebrir", + "timeslider.month.may": "Mayyu", + "timeslider.month.june": "Yunyu", + "timeslider.month.july": "Yulyu", + "timeslider.month.august": "Ɣuct", + "timeslider.month.september": "Ctamber", + "timeslider.month.october": "Tuber", + "timeslider.month.november": "Wamber", + "timeslider.month.december": "Dujamber", + "timeslider.unnamedauthors": "{{num}}{[plural(num) one: ameskar udrig, other: imeskaren udrigen]}", + "pad.savedrevs.marked": "Aceggir-agi yettwacreḍ tura d aceggir yettwaskelsen", + "pad.savedrevs.timeslider": "Tzemreḍ ad waliḍ iceggiren yettwaskelsen ticki teldiḍ amazray", + "pad.userlist.entername": "Sekcem isem-ik", + "pad.userlist.unnamed": "udrig", + "pad.userlist.guest": "Inebgi", + "pad.userlist.deny": "Agwi", + "pad.userlist.approve": "Qbel", + "pad.editbar.clearcolors": "Sfeḍ akk initen icudden ar imeskaren deg isemliyen meṛṛa?", + "pad.impexp.importbutton": "Kter tura", + "pad.impexp.importing": "Aktar iteddu...", + "pad.impexp.confirmimport": "Akter n ufaylu ad yesfeɛj aḍris amiran deg upad. Tebɣiḍ ad tkemleḍ?", + "pad.impexp.convertFailed": "Ur nezmir ara ad d-nekter afaylu-agi. Ma ulac aɣilif seqdec amasal n isemli-nniḍen neɣ nɣel/senteḍ s ufus.", + "pad.impexp.padHasData": "Ur nezmir ara ad d-nekter afaylu-agi acku apad-agi ibeddel yakan, ma ulac aɣilif, kter ar upad amaynut", + "pad.impexp.uploadFailed": "Asali yecceḍ, ma ulac aɣilif ɛreḍ tikelt-nniḍen", + "pad.impexp.importfailed": "Akter ur yeddi ara", + "pad.impexp.copypaste": "Ma ulac aɣilif nɣel/senteḍ", + "pad.impexp.exportdisabled": "Aɣewwaṛ n usifeḍ s umasal{{type}} yensa. Nermes anebdal-ik n unagraw i ugar n telqayt." +} diff --git a/src/locales/ko.json b/src/locales/ko.json index 0d0a10424..19625eaea 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -6,7 +6,8 @@ "Revi", "Kurousagi", "SeoJeongHo", - "Ykhwong" + "Ykhwong", + "CYAN" ] }, "index.newPad": "새 패드", @@ -27,7 +28,7 @@ "pad.toolbar.savedRevision.title": "판 저장", "pad.toolbar.settings.title": "설정", "pad.toolbar.embed.title": "이 패드를 공유하고 포함하기", - "pad.toolbar.showusers.title": "이 패드에 사용자 보기", + "pad.toolbar.showusers.title": "이 패드의 사용자 보기", "pad.colorpicker.save": "저장", "pad.colorpicker.cancel": "취소", "pad.loading": "불러오는 중...", @@ -38,7 +39,7 @@ "pad.settings.padSettings": "패드 설정", "pad.settings.myView": "내 보기", "pad.settings.stickychat": "화면에 항상 대화 보기", - "pad.settings.chatandusers": "채트와 사용자 보기", + "pad.settings.chatandusers": "대화와 사용자 보기", "pad.settings.colorcheck": "저자 색", "pad.settings.linenocheck": "줄 번호", "pad.settings.rtlcheck": "우횡서(오른쪽에서 왼쪽으로)입니까?", @@ -54,21 +55,21 @@ "pad.importExport.exportetherpad": "Etherpad", "pad.importExport.exporthtml": "HTML", "pad.importExport.exportplain": "일반 텍스트", - "pad.importExport.exportword": "Microsoft Word", + "pad.importExport.exportword": "마이크로소프트 워드", "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "일반 텍스트나 html 형식으로만 가져올 수 있습니다. 고급 가져오기 기능에 대해서는 abiword를 설치하세요.", + "pad.importExport.exportopen": "ODF (Open Document Format, 개방형 문서 형식)", + "pad.importExport.abiword.innerHTML": "일반 텍스트나 HTML 형식으로만 가져올 수 있습니다. 고급 가져오기 기능에 대해서는 AbiWord를 설치하세요.", "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": "다른 창에서 열렸습니다", + "pad.modals.userdup.explanation": "이 패드는 이 컴퓨터에 하나 이상의 브라우저 창에서 열린 것 같습니다.", "pad.modals.userdup.advice": "대신 이 창을 사용해 다시 연결합니다.", "pad.modals.unauth": "권한이 없음", - "pad.modals.unauth.explanation": "이 문서를 보는 동안 권한이 바뀌었습니다. 다시 연결을 시도하세요.", - "pad.modals.looping.explanation": "동기 서버와의 통신 문제가 있습니다.", + "pad.modals.unauth.explanation": "이 페이지를 보는 동안 권한이 바뀌었습니다. 연결을 다시 시도하세요.", + "pad.modals.looping.explanation": "동기화 서버와 통신 문제가 있습니다.", "pad.modals.looping.cause": "아마 호환되지 않는 방화벽이나 프록시를 통해 연결되어 있습니다.", "pad.modals.initsocketfail": "서버에 연결할 수 없습니다.", "pad.modals.initsocketfail.explanation": "동기 서버에 연결할 수 없습니다.", diff --git a/src/locales/sl.json b/src/locales/sl.json index 6748ac8d4..6e81d9ab8 100644 --- a/src/locales/sl.json +++ b/src/locales/sl.json @@ -19,23 +19,23 @@ "pad.toolbar.unindent.title": "Zamik levo (Shift+TAB)", "pad.toolbar.undo.title": "Razveljavi (Ctrl-Z)", "pad.toolbar.redo.title": "Ponovno uveljavi (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Počisti barvo avtorstva (Ctrl+Shift+C)", + "pad.toolbar.clearAuthorship.title": "Počisti barve avtorstva (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Izvozi/Uvozi različne oblike zapisov", - "pad.toolbar.timeslider.title": "Drsnik zgodovine", - "pad.toolbar.savedRevision.title": "Shrani predelavo", + "pad.toolbar.timeslider.title": "Časovni trak", + "pad.toolbar.savedRevision.title": "Shrani redakcijo", "pad.toolbar.settings.title": "Nastavitve", - "pad.toolbar.embed.title": "Deli in vključi dokument", + "pad.toolbar.embed.title": "Deli in vključi ta dokument", "pad.toolbar.showusers.title": "Pokaži uporabnike dokumenta", "pad.colorpicker.save": "Shrani", "pad.colorpicker.cancel": "Prekliči", "pad.loading": "Nalaganje ...", "pad.noCookie": "Piškotka ni bilo mogoče najti. Prosimo, dovolite piškotke v vašem brskalniku!", - "pad.passwordRequired": "Za dostop do dokumenta je zahtevano geslo.", - "pad.permissionDenied": "Za dostop do dokumenta so zahtevana posebna dovoljenja.", - "pad.wrongPassword": "Vpisano geslo je napačno.", + "pad.passwordRequired": "Za dostop do dokumenta potrebujete geslo.", + "pad.permissionDenied": "Nimate dovoljenja za dostop do tega dokumenta.", + "pad.wrongPassword": "Vpisano geslo je napačno", "pad.settings.padSettings": "Nastavitve dokumenta", - "pad.settings.myView": "Pogled", - "pad.settings.stickychat": "Vsebina klepeta je vedno na zaslonu.", + "pad.settings.myView": "Moj pogled", + "pad.settings.stickychat": "Vsebina klepeta je vedno na zaslonu", "pad.settings.chatandusers": "Prikaži klepet in uporabnike", "pad.settings.colorcheck": "Barve avtorstva", "pad.settings.linenocheck": "Številke vrstic", @@ -55,43 +55,43 @@ "pad.importExport.exportword": "DOC (zapis Microsoft Word)", "pad.importExport.exportpdf": "PDF (zapis Acrobat PDF)", "pad.importExport.exportopen": "ODF (zapis Open Document)", - "pad.importExport.abiword.innerHTML": "Uvoziti je mogoče le običajno neoblikovano besedilo in zapise HTML. Za naprednejše zmožnosti namestite program Abiword.", + "pad.importExport.abiword.innerHTML": "Uvoziti je mogoče le običajno neoblikovano besedilo in zapise HTML. Za naprednejše zmožnosti namestite program AbiWord.", "pad.modals.connected": "Povezano.", "pad.modals.reconnecting": "Poteka povezovanje z dokumentom ...", - "pad.modals.forcereconnect": "Vsili ponovno povezavo.", + "pad.modals.forcereconnect": "Vsili ponovno povezavo", "pad.modals.reconnecttimer": "Poskus ponovne vzpostavitve povezave čez", "pad.modals.cancel": "Prekliči", - "pad.modals.userdup": "Dokument je že odprt v v drugem oknu.", + "pad.modals.userdup": "Dokument je že odprt v v drugem oknu", "pad.modals.userdup.explanation": "Videti je, da je ta dokument odprt v več kot enem oknu brskalnika na tem računalniku.", "pad.modals.userdup.advice": "Ponovno vzpostavite povezavo in uporabljajte to okno.", "pad.modals.unauth": "Nepooblaščen dostop", - "pad.modals.unauth.explanation": "Med pregledovanjem te strani so se dovoljenja za ogled spremenila. Treba se bo znova povezati.", - "pad.modals.looping.explanation": "Zaznane so težave s povezavo za usklajevanje s strežnikom.", - "pad.modals.looping.cause": "Morda je vzpostavljena povezava preko neustrezno nastavljenega požarnega zidu ali posredniškega strežnika.", - "pad.modals.initsocketfail": "Dostop do strežnika ni mogoč.", + "pad.modals.unauth.explanation": "Med pregledovanjem te strani so se dovoljenja za ogled spremenila. Poskusite se ponovno povezati.", + "pad.modals.looping.explanation": "Zaznane so težave pri komunikaciji s strežnikom za usklajevanje.", + "pad.modals.looping.cause": "Morda ste se povezali preko neustrezno nastavljenega požarnega zidu ali posredniškega strežnika.", + "pad.modals.initsocketfail": "Strežnika je nedosegljiv.", "pad.modals.initsocketfail.explanation": "Povezava s strežnikom za usklajevanje ni mogoča.", - "pad.modals.initsocketfail.cause": "Najverjetneje je težava v brskalniku, ali pa so težave z internetno povezavo.", + "pad.modals.initsocketfail.cause": "Najverjetneje gre za težavo z vašim brskalnikom, ali internetno povezavo.", "pad.modals.slowcommit.explanation": "Strežnik se ne odziva.", - "pad.modals.slowcommit.cause": "Najverjetneje je prišlo do napake med vzpostavitvijo povezave.", - "pad.modals.badChangeset.explanation": "Urejanje, ki ste ga naredili, je sinhronizacijski strežnik označil kot nelegalno.", - "pad.modals.badChangeset.cause": "Razlog za to je morda napačna konfiguracija strežnika ali neko drugo nepričakovano vedenje. Prosimo, stopite v stik z upravljavcem storitve, če menite, da gre za napako. Poskusite se ponovno povezati, da nadaljujete z urejanjem.", + "pad.modals.slowcommit.cause": "Možen vzrok so težave z omrežno povezljivostjo.", + "pad.modals.badChangeset.explanation": "Urejanje, ki ste ga naredili, je strežnik za usklajevanje označil kot nedovoljeno.", + "pad.modals.badChangeset.cause": "Razlog za to je morda napačna konfiguracija strežnika ali neko drugo nepričakovano vedenje. Prosimo, stopite v stik z skrbnikom storitve, če menite, da gre za napako. Poskusite se ponovno povezati, da nadaljujete z urejanjem.", "pad.modals.corruptPad.explanation": "Dokument, do katerega želite dostopati, je poškodovan.", - "pad.modals.corruptPad.cause": "Razlog za to je morda napačna konfiguracija strežnika ali neko drugo nepričakovano vedenje. Prosimo, stopite v stik z upravljavcem storitve.", + "pad.modals.corruptPad.cause": "Razlog za to je morda napačna konfiguracija strežnika ali neko drugo nepričakovano vedenje. Prosimo, stopite v stik s skrbnikom storitve.", "pad.modals.deleted": "Izbrisano.", - "pad.modals.deleted.explanation": "Dokument je odstranjen.", - "pad.modals.disconnected": "Povezava je prekinjena.", - "pad.modals.disconnected.explanation": "Povezava s strežnikom je bila prekinjena.", - "pad.modals.disconnected.cause": "Strežnik je morda nedosegljiv. Prosimo, obvestite skrbnika storitve, če se to zgodi večkrat.", + "pad.modals.deleted.explanation": "Dokument je bil odstranjen.", + "pad.modals.disconnected": "Vaša povezava je bila prekinjena.", + "pad.modals.disconnected.explanation": "Povezava s strežnikom je bila izgubljena.", + "pad.modals.disconnected.cause": "Strežnik morda ni na voljo. Prosimo, obvestite skrbnika storitve, če se to zgodi večkrat.", "pad.share": "Določi souporabo dokumenta", "pad.share.readonly": "Le za branje", "pad.share.link": "Povezava", - "pad.share.emebdcode": "Vstavi naslov URL", + "pad.share.emebdcode": "URL za vključitev", "pad.chat": "Klepet", "pad.chat.title": "Odpri klepetalno okno dokumenta.", "pad.chat.loadmessages": "Naloži več sporočil", - "timeslider.pageTitle": "Zgodovina dokumenta {{appTitle}}", + "timeslider.pageTitle": "Časovni trak {{appTitle}}", "timeslider.toolbar.returnbutton": "Vrni se na dokument", - "timeslider.toolbar.authors": "Autorji:", + "timeslider.toolbar.authors": "Avtorji:", "timeslider.toolbar.authorsList": "Ni določenih avtorjev", "timeslider.toolbar.exportlink.title": "Izvozi", "timeslider.exportCurrent": "Izvozi trenutno različico kot:", @@ -99,7 +99,7 @@ "timeslider.saved": "Shranjeno {{day}}.{{month}}.{{year}}", "timeslider.playPause": "Predvajaj/začasno ustavi vsebino dokumenta", "timeslider.backRevision": "Pojdi eno redakcijo nazaj v tem dokumentu", - "timeslider.forwardRevision": "Pojdi redakcijo naprej v tem dokumentu", + "timeslider.forwardRevision": "Pojdi eno redakcijo naprej v tem dokumentu", "timeslider.dateformat": "{{day}}.{{month}}.{{year}} {{hours}}:{{minutes}}:{{seconds}}", "timeslider.month.january": "Januar", "timeslider.month.february": "Februar", @@ -114,9 +114,9 @@ "timeslider.month.november": "November", "timeslider.month.december": "December", "timeslider.unnamedauthors": "{{num}} {[plural(num) one: neimenovan avtor, plural(num) two: neimenovana avtorja, plural(num) few: neimenovani avtorji, other: neimenovanih avtorjev ]}", - "pad.savedrevs.marked": "Ta predelava je označena kot shranjena predelava.", - "pad.savedrevs.timeslider": "Shranjene revizije si lahko ogledate s pomočjo časovnega traku", - "pad.userlist.entername": "Vpišite ime", + "pad.savedrevs.marked": "Ta redakcija je zdaj označena kot shranjena redakcija", + "pad.savedrevs.timeslider": "Shranjene redakcije si lahko ogledate s pomočjo časovnega traku", + "pad.userlist.entername": "Vnesite svoje ime", "pad.userlist.unnamed": "neimenovana oseba", "pad.userlist.guest": "Gost", "pad.userlist.deny": "Zavrni", @@ -125,10 +125,10 @@ "pad.impexp.importbutton": "Uvozi takoj", "pad.impexp.importing": "Poteka uvažanje ...", "pad.impexp.confirmimport": "Uvoz datoteke prepiše obstoječe besedilo dokumenta. Ali ste prepričani, da želite nadaljevati?", - "pad.impexp.convertFailed": "Datoteke ni mogoče uvoziti. Uporabiti je treba enega izmed podprtih zapisov dokumentov ali pa vsebino prilepiti ročno.", + "pad.impexp.convertFailed": "Datoteke ni bilo mogoče uvoziti. Prosimo uporabite drug podprt zapis dokumenta ali pa vsebino prilepite ročno", "pad.impexp.padHasData": "Nismo mogli uvoziti datoteke, ker dokument že vsebuje spremembe. Prosimo, uvozite datoteko v nov dokument", - "pad.impexp.uploadFailed": "Nalaganje je spodletelo, poskusite znova.", - "pad.impexp.importfailed": "Uvoz je spodletel.", - "pad.impexp.copypaste": "Vsebino kopirajte in prilepite.", + "pad.impexp.uploadFailed": "Nalaganje je spodletelo, prosimo poskusite znova", + "pad.impexp.importfailed": "Uvoz je spodletel", + "pad.impexp.copypaste": "Vsebino kopirajte in prilepite", "pad.impexp.exportdisabled": "Izvoz v zapis {{type}} je onemogočen. Za več podrobnosti stopite v stik s skrbnikom." } diff --git a/src/locales/sv.json b/src/locales/sv.json index c137f299d..e73c3e7f3 100644 --- a/src/locales/sv.json +++ b/src/locales/sv.json @@ -54,7 +54,7 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Du kan endast importera från oformaterad text eller HTML-format. För mer avancerade importeringsfunktioner, var god installera abiword.", + "pad.importExport.abiword.innerHTML": "Du kan endast importera från oformaterad text eller HTML-format. För mer avancerade importfunktioner, var god installera AbiWord.", "pad.modals.connected": "Ansluten.", "pad.modals.reconnecting": "Återansluter till ditt block...", "pad.modals.forcereconnect": "Tvinga återanslutning", From 8abba28756473d39d68c975e69cf23ba3c53ecfe Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 3 Aug 2017 10:39:40 +0200 Subject: [PATCH 082/102] Localisation updates from https://translatewiki.net. --- src/locales/it.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/locales/it.json b/src/locales/it.json index d28ba9c7b..d7d7c095a 100644 --- a/src/locales/it.json +++ b/src/locales/it.json @@ -57,7 +57,7 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "È possibile importare solo i formati di testo semplice o HTML. Per metodi più avanzati di importazione installare Abiword.", + "pad.importExport.abiword.innerHTML": "È possibile importare solo i formati di testo semplice o HTML. Per metodi più avanzati di importazione installare AbiWord.", "pad.modals.connected": "Connesso.", "pad.modals.reconnecting": "Riconnessione al pad in corso...", "pad.modals.forcereconnect": "Forza la riconnessione", From f10e60713bd1941ff83d69383416425033fa4163 Mon Sep 17 00:00:00 2001 From: Martin Honermeyer Date: Fri, 4 Aug 2017 15:42:25 +0200 Subject: [PATCH 083/102] Update socket.io to 1.7.3 That in turn upgrades engine.io to 1.8.2. This fixes a crash for me when running behind a traefik reverse proxy. https://github.com/socketio/engine.io/issues/465 --- src/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package.json b/src/package.json index ca86258f5..3bb76947e 100644 --- a/src/package.json +++ b/src/package.json @@ -16,7 +16,7 @@ "request" : "2.55.0", "etherpad-require-kernel" : "1.0.9", "resolve" : "1.1.7", - "socket.io" : "1.6.0", + "socket.io" : "1.7.3", "ueberdb2" : "0.3.0", "express" : "4.13.4", "express-session" : "1.13.0", From e93d6071657cc2a807f44cb05de50d265bee7c3a Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 7 Aug 2017 07:22:05 +0200 Subject: [PATCH 084/102] Localisation updates from https://translatewiki.net. --- src/locales/skr-arab.json | 68 +++++++++++++++++++++++++++++++++++++++ src/locales/sl.json | 2 +- 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 src/locales/skr-arab.json diff --git a/src/locales/skr-arab.json b/src/locales/skr-arab.json new file mode 100644 index 000000000..5ed2824dd --- /dev/null +++ b/src/locales/skr-arab.json @@ -0,0 +1,68 @@ +{ + "@metadata": { + "authors": [ + "Saraiki" + ] + }, + "index.newPad": "نواں پیڈ", + "pad.toolbar.bold.title": "بولڈ(Ctrl+B)", + "pad.toolbar.italic.title": "ترچھے (Ctrl+I)", + "pad.toolbar.underline.title": "ہیٹھ لکیر (Ctrl+U)", + "pad.toolbar.savedRevision.title": "رویژن بچاؤ", + "pad.toolbar.settings.title": "ترتیباں", + "pad.colorpicker.save": "بچاؤ", + "pad.colorpicker.cancel": "منسوخ", + "pad.loading": "لوڈ تھیندا پئے۔۔۔", + "pad.wrongPassword": "تہاݙ پاسورڈ غلط ہے", + "pad.settings.padSettings": "پیڈ ترتیباں", + "pad.settings.fontType": "فونٹ قسم:", + "pad.settings.language": "زبان:", + "pad.importExport.importSuccessful": "کامیاب!", + "pad.importExport.exportetherpad": "ایتھرپیڈ", + "pad.importExport.exporthtml": "ایث ٹی ایم ایل", + "pad.importExport.exportplain": "سادہ متن", + "pad.importExport.exportword": "مائیکروسافٹ ورڈ", + "pad.importExport.exportpdf": "پی ڈی ایف", + "pad.modals.connected": "ڄُڑ ڳیا۔", + "pad.modals.cancel": "منسوخ", + "pad.modals.unauth": "اجازت کائنی", + "pad.modals.initsocketfail": "سرور تائیں پہنچݨ ممکن کائنی", + "pad.modals.slowcommit.explanation": "سرور توں جواب کائنی امدا پیا", + "pad.modals.deleted": "مٹا ݙتے", + "pad.modals.deleted.explanation": "ایہ پیڈ ہٹا ݙتا ڳئے۔", + "pad.modals.disconnected": "تہاݙا کنکشن مُک ڳئے", + "pad.share": "ایہ پیڈ شیئر کرو", + "pad.share.readonly": "صرف پڑھو", + "pad.share.link": "ربط", + "pad.share.emebdcode": "امنیڈ یو آر ایل", + "pad.chat": "چیٹ", + "pad.chat.loadmessages": "ٻئے سنیہے لوڈ کرو", + "timeslider.toolbar.returnbutton": "واپس پیڈ تے ونڄو", + "timeslider.toolbar.authors": "مصنف:", + "timeslider.toolbar.authorsList": "کوئی مصنف کائنی", + "timeslider.toolbar.exportlink.title": "ٻاہر بھیڄو", + "timeslider.version": "ورژن {{version}}", + "timeslider.saved": "محفوظ تھیا {{month}} {{day}}, {{year}}", + "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", + "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": "ٻاہروں آ نی سڳے" +} diff --git a/src/locales/sl.json b/src/locales/sl.json index 6e81d9ab8..50333132e 100644 --- a/src/locales/sl.json +++ b/src/locales/sl.json @@ -55,7 +55,7 @@ "pad.importExport.exportword": "DOC (zapis Microsoft Word)", "pad.importExport.exportpdf": "PDF (zapis Acrobat PDF)", "pad.importExport.exportopen": "ODF (zapis Open Document)", - "pad.importExport.abiword.innerHTML": "Uvoziti je mogoče le običajno neoblikovano besedilo in zapise HTML. Za naprednejše zmožnosti namestite program AbiWord.", + "pad.importExport.abiword.innerHTML": "Uvoziti je mogoče le običajno neoblikovano besedilo in zapise HTML. Za naprednejše zmožnosti namestite program AbiWord.", "pad.modals.connected": "Povezano.", "pad.modals.reconnecting": "Poteka povezovanje z dokumentom ...", "pad.modals.forcereconnect": "Vsili ponovno povezavo", From 9b9d604c09ca54ae3e2b179888a41ed236b7daf0 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 14 Aug 2017 08:14:37 +0200 Subject: [PATCH 085/102] Localisation updates from https://translatewiki.net. --- src/locales/sk.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/locales/sk.json b/src/locales/sk.json index b1dc0a202..e199945a8 100644 --- a/src/locales/sk.json +++ b/src/locales/sk.json @@ -56,10 +56,12 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Importovať môžete len čistý text alebo HTML. Pre pokročilejšie funkcie importu prosím nainštalujte „Abiword“.", + "pad.importExport.abiword.innerHTML": "Importovať môžete len čistý text alebo HTML. Pre pokročilejšie funkcie importu prosím nainštalujte „AbiWord“.", "pad.modals.connected": "Pripojené.", "pad.modals.reconnecting": "Opätovné pripájanie k vášmu Padu...", "pad.modals.forcereconnect": "Vynútiť znovupripojenie", + "pad.modals.reconnecttimer": "Skúšam sa pripojiť", + "pad.modals.cancel": "Zrušiť", "pad.modals.userdup": "Otvorené v inom okne", "pad.modals.userdup.explanation": "Zdá sa, že tento Pad je na tomto počítači otvorený vo viacerých oknách prehliadača.", "pad.modals.userdup.advice": "Pre použitie tohoto okna se musíte znovu pripojiť.", From 6bcaa00a4ba70320a390457c90dbf699d0e4a4b9 Mon Sep 17 00:00:00 2001 From: Luiza Pagliari Date: Tue, 15 Aug 2017 10:22:59 -0300 Subject: [PATCH 086/102] [feat] Update l10n lib (#3248) Last update was from 2014. Fix #3244. --- src/static/js/html10n.js | 219 ++++++++++++++++++++++++--------------- 1 file changed, 133 insertions(+), 86 deletions(-) diff --git a/src/static/js/html10n.js b/src/static/js/html10n.js index eecbaa0a2..f2d79ab4a 100644 --- a/src/static/js/html10n.js +++ b/src/static/js/html10n.js @@ -21,18 +21,30 @@ * IN THE SOFTWARE. */ window.html10n = (function(window, document, undefined) { - + // fix console - (function() { - var noop = function() {}; - var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"]; - var console = (window.console = window.console || {}); - for (var i = 0; i < names.length; ++i) { - if (!console[names[i]]) { - console[names[i]] = noop; + var console = window.console + function interceptConsole(method){ + if (!console) return function() {} + + var original = console[method] + + // do sneaky stuff + if (original.bind){ + // Do this for normal browsers + return original.bind(console) + }else{ + return function() { + // Do this for IE + var message = Array.prototype.slice.apply(arguments).join(' ') + original(message) + } } - } - }()); + } + var consoleLog = interceptConsole('log') + , consoleWarn = interceptConsole('warn') + , consoleError = interceptConsole('warn') + // fix Array#forEach in IE // taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach @@ -80,7 +92,7 @@ window.html10n = (function(window, document, undefined) { return -1; } } - + /** * MicroEvent - to make any js object an event emitter (server or browser) */ @@ -116,7 +128,7 @@ window.html10n = (function(window, document, undefined) { destObject[props[i]] = MicroEvent.prototype[props[i]]; } } - + /** * Loader * The loader is responsible for loading @@ -127,7 +139,7 @@ window.html10n = (function(window, document, undefined) { this.cache = {} // file => contents this.langs = {} // lang => strings } - + Loader.prototype.load = function(lang, cb) { if(this.langs[lang]) return cb() @@ -136,23 +148,23 @@ window.html10n = (function(window, document, undefined) { for (var i=0, n=this.resources.length; i < n; i++) { this.fetch(this.resources[i], lang, function(e) { reqs++; - if(e) console.warn(e) - + if(e) consoleWarn(e) + if (reqs < n) return;// Call back once all reqs are completed cb && cb() }) } } } - + Loader.prototype.fetch = function(href, lang, cb) { var that = this - + if (this.cache[href]) { this.parse(lang, href, this.cache[href], cb) return; } - + var xhr = new XMLHttpRequest() xhr.open('GET', href, /*async: */true) if (xhr.overrideMimeType) { @@ -172,7 +184,7 @@ window.html10n = (function(window, document, undefined) { }; xhr.send(null); } - + Loader.prototype.parse = function(lang, currHref, data, cb) { if ('object' != typeof data) { cb(new Error('A file couldn\'t be parsed as json.')) @@ -180,7 +192,7 @@ window.html10n = (function(window, document, undefined) { } // dat alng ain't here, man! - if (!data[lang]) { + if (!data) { var msg = 'Couldn\'t find translations for '+lang , l if(~lang.indexOf('-')) lang = lang.split('-')[0] // then let's try related langs @@ -192,7 +204,7 @@ window.html10n = (function(window, document, undefined) { } if(lang != l) return cb(new Error(msg)) } - + if ('string' == typeof data[lang]) { // Import rule @@ -200,7 +212,7 @@ window.html10n = (function(window, document, undefined) { var importUrl = data[lang] // relative path - if(data[lang].indexOf("http") != 0 && data[lang].indexOf("/") != 0) { + if(data[lang].indexOf("http") != 0 && data[lang].indexOf("/") != 0) { importUrl = currHref+"/../"+data[lang] } @@ -208,29 +220,40 @@ window.html10n = (function(window, document, undefined) { return } - if ('object' != typeof data[lang]) { + if ('object' != typeof data) { cb(new Error('Translations should be specified as JSON objects!')) return } - this.langs[lang] = data[lang] + this.langs[lang] = data // TODO: Also store accompanying langs cb() } - - + + /** * The html10n object */ - var html10n = + var html10n = { language : null } MicroEvent.mixin(html10n) - + html10n.macros = {} html10n.rtl = ["ar","dv","fa","ha","he","ks","ku","ps","ur","yi"] - + + /** + * Language-Script fallbacks for Language-Region language tags, for languages that + * varies heavily on writing form and two-part locale expansion is not feasible. + * See also: https://tools.ietf.org/html/rfc4646 (RFC 4646) + */ + html10n.scripts = { + 'zh-tw': 'zh-hant', + 'zh-hk': 'zh-hant', + 'zh-cn': 'zh-hans' + } + /** * Get rules for plural forms (shared with JetPack), see: * http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html @@ -635,7 +658,7 @@ window.html10n = (function(window, document, undefined) { // return a function that gives the plural form name for a given integer var index = locales2rules[lang.replace(/-.*$/, '')]; if (!(index in pluralRules)) { - console.warn('plural form unknown for [' + lang + ']'); + consoleWarn('plural form unknown for [' + lang + ']'); return function() { return 'other'; }; } return pluralRules[index]; @@ -668,25 +691,44 @@ window.html10n = (function(window, document, undefined) { return str; }; - - /** - * Localize a document - * @param langs An array of lang codes defining fallbacks + + /** Prepare localization context: + * + * - Populate translations with strings for the indicated languages + * - adding in non-qualified versions of language codes immediately + * after any qualified (e.g., "en" for "en-GB") + * - Trigger "localized" event. + * + * @param {array} langs: diminishing-precedence lang codes, or one string. */ html10n.localize = function(langs) { - var that = this - // if only one string => create an array - if ('string' == typeof langs) langs = [langs] + var that = this, + candidates = []; + // if a single string, bundle it as an array: + if ('string' == typeof langs) { + langs = [langs]; + } - // Expand two-part locale specs - var i=0 + // Determine candidates from langs: + // - Omitting empty strings + // - Adding in non-qualified versions of country-qualified codes. langs.forEach(function(lang) { - if(!lang) return; - langs[i++] = lang; - if(~lang.indexOf('-')) langs[i++] = lang.substr(0, lang.indexOf('-')); - }) + var splat; + if(!lang) { return; } + (candidates.indexOf(lang) == -1) && candidates.push(lang); + splat = lang.split('-'); + if (splat[1]) { + (candidates.indexOf(splat[0]) == -1) && candidates.push(splat[0]); + } + }); - this.build(langs, function(er, translations) { + // Append script fallbacks for region-specific locales if applicable + for (var lang in html10n.scripts) { + i = candidates.indexOf(lang); + if (~i) candidates.splice(i, 0, html10n.scripts[lang]) + } + + this.build(candidates, function(er, translations) { html10n.translations = translations html10n.translateElement(translations) that.trigger('localized') @@ -710,18 +752,18 @@ window.html10n = (function(window, document, undefined) { // translate element itself if necessary this.translateNode(translations, element) } - + function asyncForEach(list, iterator, cb) { var i = 0 , n = list.length iterator(list[i], i, function each(err) { - if(err) console.error(err) + if(err) consoleLog(err) i++ if (i < n) return iterator(list[i],i, each); cb() }) } - + function getTranslatableChildren(element) { if(!document.querySelectorAll) { if (!element) return [] @@ -735,55 +777,62 @@ window.html10n = (function(window, document, undefined) { } return element.querySelectorAll('*[data-l10n-id]') } - + html10n.get = function(id, args) { var translations = html10n.translations - if(!translations) return console.warn('No translations available (yet)') - if(!translations[id]) return console.warn('Could not find string '+id) - + if(!translations) { + if (! html10n.quiet) { + consoleWarn('No translations available (yet)'); + } + return; + } + if(!translations[id]) return consoleWarn('Could not find string '+id) + // apply macros var str = translations[id] - + str = substMacros(id, str, args) - + // apply args str = substArguments(str, args) - + return str } - + // replace {{arguments}} with their values or the // associated translation string (based on its key) function substArguments(str, args) { - var reArgs = /\{\{\s*([a-zA-Z\.]+)\s*\}\}/ - , match - + var reArgs = /\{\{\s*([a-zA-Z_\-\.]+)\s*\}\}/, + translations = html10n.translations, + match; + while (match = reArgs.exec(str)) { if (!match || match.length < 2) return str // argument key not found var arg = match[1] , sub = '' - if (arg in args) { + if (args && (arg in args)) { sub = args[arg] } else if (arg in translations) { sub = translations[arg] } else { - console.warn('Could not find argument {{' + arg + '}}') + consoleWarn('Could not satisfy argument {{' + arg + '}}' + + ' for string "' + str + '"'); return str } str = str.substring(0, match.index) + sub + str.substr(match.index + match[0].length) } - + return str } - + // replace {[macros]} with their values function substMacros(key, str, args) { - var regex = /\{\[\s*([a-zA-Z]+)\(([a-zA-Z]+)\)((\s*([a-zA-Z]+)\: ?([ a-zA-Z{}]+),?)+)*\s*\]\}/ //.exec('{[ plural(n) other: are {{n}}, one: is ]}') + var regex = /\{\[\s*([a-zA-Z]+)\(([a-zA-Z]+)\)((\s*([a-zA-Z]+)\: ?([^,]+?),?)+)*\s*\]\}/ //.exec('{{n}} {[plural(n) one: Bomba, other: Bombe]} ]}') , match - + while(match = regex.exec(str)) { // a macro has been found // Note: at the moment, only one parameter is supported @@ -791,18 +840,18 @@ window.html10n = (function(window, document, undefined) { , paramName = match[2] , optv = match[3] , opts = {} - + if (!(macroName in html10n.macros)) continue - + if(optv) { - optv.match(/(?=\s*)([a-zA-Z]+)\: ?([ a-zA-Z{}]+)(?=,?)/g).forEach(function(arg) { + optv.match(/(?=\s*)([a-zA-Z]+)\: ?([^,\]]+)(?=,?)/g).forEach(function(arg) { var parts = arg.split(':') , name = parts[0] , value = parts[1].trim() opts[name] = value }) } - + var param if (args && paramName in args) { param = args[paramName] @@ -814,10 +863,10 @@ window.html10n = (function(window, document, undefined) { var macro = html10n.macros[macroName] str = str.substr(0, match.index) + macro(key, param, opts) + str.substr(match.index+match[0].length) } - + return str } - + /** * Applies translations to a DOM node (recursive) */ @@ -828,21 +877,21 @@ window.html10n = (function(window, document, undefined) { str.id = node.getAttribute('data-l10n-id') if (!str.id) return - if(!translations[str.id]) return console.warn('Couldn\'t find translation key '+str.id) + if(!translations[str.id]) return consoleWarn('Couldn\'t find translation key '+str.id) // get args if(window.JSON) { - str.args = JSON.parse(node.getAttribute('data-l10n-args')) + str.args = node.getAttribute('data-l10n-args') ? JSON.parse(node.getAttribute('data-l10n-args')) : []; }else{ try{ str.args = eval(node.getAttribute('data-l10n-args')) }catch(e) { - console.warn('Couldn\'t parse args for '+str.id) + consoleWarn('Couldn\'t parse args for '+str.id) } } - + str.str = html10n.get(str.id, str.args) - + // get attribute name to apply str to var prop , index = str.id.lastIndexOf('.') @@ -851,6 +900,7 @@ window.html10n = (function(window, document, undefined) { , "innerHTML": 1 , "alt": 1 , "textContent": 1 + , "placeholder": 1 , "value": 1 } if (index > 0 && str.id.substr(index + 1) in attrList) { // an attribute has been specified @@ -862,9 +912,6 @@ window.html10n = (function(window, document, undefined) { // Apply translation if (node.children.length === 0 || prop != 'textContent') { node[prop] = str.str - node.setAttribute("aria-label", str.str); // Sets the aria-label - // The idea of the above is that we always have an aria value - // This might be a bit of an abrupt solution but let's see how it goes } else { var children = node.childNodes, found = false @@ -879,11 +926,11 @@ window.html10n = (function(window, document, undefined) { } } if (!found) { - console.warn('Unexpected error: could not translate element content for key '+str.id, node) + consoleWarn('Unexpected error: could not translate element content for key '+str.id, node) } } } - + /** * Builds a translation object from a list of langs (loads the necessary translations) * @param langs Array - a list of langs sorted by priority (default langs should go last) @@ -898,11 +945,11 @@ window.html10n = (function(window, document, undefined) { }, function() { var lang langs.reverse() - + // loop through the priority array... for (var i=0, n=langs.length; i < n; i++) { lang = langs[i] - + if(!lang) continue; if(!(lang in that.loader.langs)) {// uh, we don't have this lang availbable.. // then check for related langs @@ -915,13 +962,13 @@ window.html10n = (function(window, document, undefined) { } if(lang != l) continue; } - + // ... and apply all strings of the current lang in the list // to our build object for (var string in that.loader.langs[lang]) { build[string] = that.loader.langs[lang][string] } - + // the last applied lang will be exposed as the // lang the page was translated to that.language = lang @@ -929,7 +976,7 @@ window.html10n = (function(window, document, undefined) { cb(null, build) }) } - + /** * Returns the language that was last applied to the translations hash * thus overriding most of the formerly applied langs @@ -962,7 +1009,7 @@ window.html10n = (function(window, document, undefined) { this.loader = new Loader(resources) this.trigger('indexed') } - + if (document.addEventListener) // modern browsers and IE9+ document.addEventListener('DOMContentLoaded', function() { html10n.index() From ed5213c9a25830767c87cfba19c18ab71d837b94 Mon Sep 17 00:00:00 2001 From: Luiza Pagliari Date: Tue, 15 Aug 2017 11:09:56 -0300 Subject: [PATCH 087/102] Revert "[feat] Update l10n lib (#3248)" (#3249) This reverts commit 6bcaa00a4ba70320a390457c90dbf699d0e4a4b9. --- src/static/js/html10n.js | 219 +++++++++++++++------------------------ 1 file changed, 86 insertions(+), 133 deletions(-) diff --git a/src/static/js/html10n.js b/src/static/js/html10n.js index f2d79ab4a..eecbaa0a2 100644 --- a/src/static/js/html10n.js +++ b/src/static/js/html10n.js @@ -21,30 +21,18 @@ * IN THE SOFTWARE. */ window.html10n = (function(window, document, undefined) { - + // fix console - var console = window.console - function interceptConsole(method){ - if (!console) return function() {} - - var original = console[method] - - // do sneaky stuff - if (original.bind){ - // Do this for normal browsers - return original.bind(console) - }else{ - return function() { - // Do this for IE - var message = Array.prototype.slice.apply(arguments).join(' ') - original(message) - } + (function() { + var noop = function() {}; + var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"]; + var console = (window.console = window.console || {}); + for (var i = 0; i < names.length; ++i) { + if (!console[names[i]]) { + console[names[i]] = noop; } - } - var consoleLog = interceptConsole('log') - , consoleWarn = interceptConsole('warn') - , consoleError = interceptConsole('warn') - + } + }()); // fix Array#forEach in IE // taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach @@ -92,7 +80,7 @@ window.html10n = (function(window, document, undefined) { return -1; } } - + /** * MicroEvent - to make any js object an event emitter (server or browser) */ @@ -128,7 +116,7 @@ window.html10n = (function(window, document, undefined) { destObject[props[i]] = MicroEvent.prototype[props[i]]; } } - + /** * Loader * The loader is responsible for loading @@ -139,7 +127,7 @@ window.html10n = (function(window, document, undefined) { this.cache = {} // file => contents this.langs = {} // lang => strings } - + Loader.prototype.load = function(lang, cb) { if(this.langs[lang]) return cb() @@ -148,23 +136,23 @@ window.html10n = (function(window, document, undefined) { for (var i=0, n=this.resources.length; i < n; i++) { this.fetch(this.resources[i], lang, function(e) { reqs++; - if(e) consoleWarn(e) - + if(e) console.warn(e) + if (reqs < n) return;// Call back once all reqs are completed cb && cb() }) } } } - + Loader.prototype.fetch = function(href, lang, cb) { var that = this - + if (this.cache[href]) { this.parse(lang, href, this.cache[href], cb) return; } - + var xhr = new XMLHttpRequest() xhr.open('GET', href, /*async: */true) if (xhr.overrideMimeType) { @@ -184,7 +172,7 @@ window.html10n = (function(window, document, undefined) { }; xhr.send(null); } - + Loader.prototype.parse = function(lang, currHref, data, cb) { if ('object' != typeof data) { cb(new Error('A file couldn\'t be parsed as json.')) @@ -192,7 +180,7 @@ window.html10n = (function(window, document, undefined) { } // dat alng ain't here, man! - if (!data) { + if (!data[lang]) { var msg = 'Couldn\'t find translations for '+lang , l if(~lang.indexOf('-')) lang = lang.split('-')[0] // then let's try related langs @@ -204,7 +192,7 @@ window.html10n = (function(window, document, undefined) { } if(lang != l) return cb(new Error(msg)) } - + if ('string' == typeof data[lang]) { // Import rule @@ -212,7 +200,7 @@ window.html10n = (function(window, document, undefined) { var importUrl = data[lang] // relative path - if(data[lang].indexOf("http") != 0 && data[lang].indexOf("/") != 0) { + if(data[lang].indexOf("http") != 0 && data[lang].indexOf("/") != 0) { importUrl = currHref+"/../"+data[lang] } @@ -220,40 +208,29 @@ window.html10n = (function(window, document, undefined) { return } - if ('object' != typeof data) { + if ('object' != typeof data[lang]) { cb(new Error('Translations should be specified as JSON objects!')) return } - this.langs[lang] = data + this.langs[lang] = data[lang] // TODO: Also store accompanying langs cb() } - - + + /** * The html10n object */ - var html10n = + var html10n = { language : null } MicroEvent.mixin(html10n) - + html10n.macros = {} html10n.rtl = ["ar","dv","fa","ha","he","ks","ku","ps","ur","yi"] - - /** - * Language-Script fallbacks for Language-Region language tags, for languages that - * varies heavily on writing form and two-part locale expansion is not feasible. - * See also: https://tools.ietf.org/html/rfc4646 (RFC 4646) - */ - html10n.scripts = { - 'zh-tw': 'zh-hant', - 'zh-hk': 'zh-hant', - 'zh-cn': 'zh-hans' - } - + /** * Get rules for plural forms (shared with JetPack), see: * http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html @@ -658,7 +635,7 @@ window.html10n = (function(window, document, undefined) { // return a function that gives the plural form name for a given integer var index = locales2rules[lang.replace(/-.*$/, '')]; if (!(index in pluralRules)) { - consoleWarn('plural form unknown for [' + lang + ']'); + console.warn('plural form unknown for [' + lang + ']'); return function() { return 'other'; }; } return pluralRules[index]; @@ -691,44 +668,25 @@ window.html10n = (function(window, document, undefined) { return str; }; - - /** Prepare localization context: - * - * - Populate translations with strings for the indicated languages - * - adding in non-qualified versions of language codes immediately - * after any qualified (e.g., "en" for "en-GB") - * - Trigger "localized" event. - * - * @param {array} langs: diminishing-precedence lang codes, or one string. + + /** + * Localize a document + * @param langs An array of lang codes defining fallbacks */ html10n.localize = function(langs) { - var that = this, - candidates = []; - // if a single string, bundle it as an array: - if ('string' == typeof langs) { - langs = [langs]; - } + var that = this + // if only one string => create an array + if ('string' == typeof langs) langs = [langs] - // Determine candidates from langs: - // - Omitting empty strings - // - Adding in non-qualified versions of country-qualified codes. + // Expand two-part locale specs + var i=0 langs.forEach(function(lang) { - var splat; - if(!lang) { return; } - (candidates.indexOf(lang) == -1) && candidates.push(lang); - splat = lang.split('-'); - if (splat[1]) { - (candidates.indexOf(splat[0]) == -1) && candidates.push(splat[0]); - } - }); + if(!lang) return; + langs[i++] = lang; + if(~lang.indexOf('-')) langs[i++] = lang.substr(0, lang.indexOf('-')); + }) - // Append script fallbacks for region-specific locales if applicable - for (var lang in html10n.scripts) { - i = candidates.indexOf(lang); - if (~i) candidates.splice(i, 0, html10n.scripts[lang]) - } - - this.build(candidates, function(er, translations) { + this.build(langs, function(er, translations) { html10n.translations = translations html10n.translateElement(translations) that.trigger('localized') @@ -752,18 +710,18 @@ window.html10n = (function(window, document, undefined) { // translate element itself if necessary this.translateNode(translations, element) } - + function asyncForEach(list, iterator, cb) { var i = 0 , n = list.length iterator(list[i], i, function each(err) { - if(err) consoleLog(err) + if(err) console.error(err) i++ if (i < n) return iterator(list[i],i, each); cb() }) } - + function getTranslatableChildren(element) { if(!document.querySelectorAll) { if (!element) return [] @@ -777,62 +735,55 @@ window.html10n = (function(window, document, undefined) { } return element.querySelectorAll('*[data-l10n-id]') } - + html10n.get = function(id, args) { var translations = html10n.translations - if(!translations) { - if (! html10n.quiet) { - consoleWarn('No translations available (yet)'); - } - return; - } - if(!translations[id]) return consoleWarn('Could not find string '+id) - + if(!translations) return console.warn('No translations available (yet)') + if(!translations[id]) return console.warn('Could not find string '+id) + // apply macros var str = translations[id] - + str = substMacros(id, str, args) - + // apply args str = substArguments(str, args) - + return str } - + // replace {{arguments}} with their values or the // associated translation string (based on its key) function substArguments(str, args) { - var reArgs = /\{\{\s*([a-zA-Z_\-\.]+)\s*\}\}/, - translations = html10n.translations, - match; - + var reArgs = /\{\{\s*([a-zA-Z\.]+)\s*\}\}/ + , match + while (match = reArgs.exec(str)) { if (!match || match.length < 2) return str // argument key not found var arg = match[1] , sub = '' - if (args && (arg in args)) { + if (arg in args) { sub = args[arg] } else if (arg in translations) { sub = translations[arg] } else { - consoleWarn('Could not satisfy argument {{' + arg + '}}' + - ' for string "' + str + '"'); + console.warn('Could not find argument {{' + arg + '}}') return str } str = str.substring(0, match.index) + sub + str.substr(match.index + match[0].length) } - + return str } - + // replace {[macros]} with their values function substMacros(key, str, args) { - var regex = /\{\[\s*([a-zA-Z]+)\(([a-zA-Z]+)\)((\s*([a-zA-Z]+)\: ?([^,]+?),?)+)*\s*\]\}/ //.exec('{{n}} {[plural(n) one: Bomba, other: Bombe]} ]}') + var regex = /\{\[\s*([a-zA-Z]+)\(([a-zA-Z]+)\)((\s*([a-zA-Z]+)\: ?([ a-zA-Z{}]+),?)+)*\s*\]\}/ //.exec('{[ plural(n) other: are {{n}}, one: is ]}') , match - + while(match = regex.exec(str)) { // a macro has been found // Note: at the moment, only one parameter is supported @@ -840,18 +791,18 @@ window.html10n = (function(window, document, undefined) { , paramName = match[2] , optv = match[3] , opts = {} - + if (!(macroName in html10n.macros)) continue - + if(optv) { - optv.match(/(?=\s*)([a-zA-Z]+)\: ?([^,\]]+)(?=,?)/g).forEach(function(arg) { + optv.match(/(?=\s*)([a-zA-Z]+)\: ?([ a-zA-Z{}]+)(?=,?)/g).forEach(function(arg) { var parts = arg.split(':') , name = parts[0] , value = parts[1].trim() opts[name] = value }) } - + var param if (args && paramName in args) { param = args[paramName] @@ -863,10 +814,10 @@ window.html10n = (function(window, document, undefined) { var macro = html10n.macros[macroName] str = str.substr(0, match.index) + macro(key, param, opts) + str.substr(match.index+match[0].length) } - + return str } - + /** * Applies translations to a DOM node (recursive) */ @@ -877,21 +828,21 @@ window.html10n = (function(window, document, undefined) { str.id = node.getAttribute('data-l10n-id') if (!str.id) return - if(!translations[str.id]) return consoleWarn('Couldn\'t find translation key '+str.id) + if(!translations[str.id]) return console.warn('Couldn\'t find translation key '+str.id) // get args if(window.JSON) { - str.args = node.getAttribute('data-l10n-args') ? JSON.parse(node.getAttribute('data-l10n-args')) : []; + str.args = JSON.parse(node.getAttribute('data-l10n-args')) }else{ try{ str.args = eval(node.getAttribute('data-l10n-args')) }catch(e) { - consoleWarn('Couldn\'t parse args for '+str.id) + console.warn('Couldn\'t parse args for '+str.id) } } - + str.str = html10n.get(str.id, str.args) - + // get attribute name to apply str to var prop , index = str.id.lastIndexOf('.') @@ -900,7 +851,6 @@ window.html10n = (function(window, document, undefined) { , "innerHTML": 1 , "alt": 1 , "textContent": 1 - , "placeholder": 1 , "value": 1 } if (index > 0 && str.id.substr(index + 1) in attrList) { // an attribute has been specified @@ -912,6 +862,9 @@ window.html10n = (function(window, document, undefined) { // Apply translation if (node.children.length === 0 || prop != 'textContent') { node[prop] = str.str + node.setAttribute("aria-label", str.str); // Sets the aria-label + // The idea of the above is that we always have an aria value + // This might be a bit of an abrupt solution but let's see how it goes } else { var children = node.childNodes, found = false @@ -926,11 +879,11 @@ window.html10n = (function(window, document, undefined) { } } if (!found) { - consoleWarn('Unexpected error: could not translate element content for key '+str.id, node) + console.warn('Unexpected error: could not translate element content for key '+str.id, node) } } } - + /** * Builds a translation object from a list of langs (loads the necessary translations) * @param langs Array - a list of langs sorted by priority (default langs should go last) @@ -945,11 +898,11 @@ window.html10n = (function(window, document, undefined) { }, function() { var lang langs.reverse() - + // loop through the priority array... for (var i=0, n=langs.length; i < n; i++) { lang = langs[i] - + if(!lang) continue; if(!(lang in that.loader.langs)) {// uh, we don't have this lang availbable.. // then check for related langs @@ -962,13 +915,13 @@ window.html10n = (function(window, document, undefined) { } if(lang != l) continue; } - + // ... and apply all strings of the current lang in the list // to our build object for (var string in that.loader.langs[lang]) { build[string] = that.loader.langs[lang][string] } - + // the last applied lang will be exposed as the // lang the page was translated to that.language = lang @@ -976,7 +929,7 @@ window.html10n = (function(window, document, undefined) { cb(null, build) }) } - + /** * Returns the language that was last applied to the translations hash * thus overriding most of the formerly applied langs @@ -1009,7 +962,7 @@ window.html10n = (function(window, document, undefined) { this.loader = new Loader(resources) this.trigger('indexed') } - + if (document.addEventListener) // modern browsers and IE9+ document.addEventListener('DOMContentLoaded', function() { html10n.index() From 392d649f4dfcd652d213fce4e9a70249d3725448 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 17 Aug 2017 15:31:28 +0200 Subject: [PATCH 088/102] Localisation updates from https://translatewiki.net. --- src/locales/da.json | 15 +++++++++++++-- src/locales/oc.json | 4 +++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/locales/da.json b/src/locales/da.json index 662e9afbd..06280b8e7 100644 --- a/src/locales/da.json +++ b/src/locales/da.json @@ -3,7 +3,8 @@ "authors": [ "Christian List", "Peter Alberti", - "Steenth" + "Steenth", + "Joedalton" ] }, "index.newPad": "Ny Pad", @@ -28,12 +29,14 @@ "pad.colorpicker.save": "Gem", "pad.colorpicker.cancel": "Afbryd", "pad.loading": "Indlæser ...", + "pad.noCookie": "Cookie kunne ikke findes. Tillad venligst cookier i din browser!", "pad.passwordRequired": "Du skal bruge en adgangskode for at få adgang til denne pad", "pad.permissionDenied": "Du har ikke tilladelse til at få adgang til denne pad.", "pad.wrongPassword": "Din adgangskode er forkert", "pad.settings.padSettings": "Pad indstillinger", "pad.settings.myView": "Min visning", "pad.settings.stickychat": "Chat altid på skærmen", + "pad.settings.chatandusers": "Vis snak (chat) og brugere", "pad.settings.colorcheck": "Forfatterskabsfarver", "pad.settings.linenocheck": "Linjenumre", "pad.settings.rtlcheck": "Læse indhold fra højre mod venstre?", @@ -46,15 +49,18 @@ "pad.importExport.import": "Uploade en tekstfil eller dokument", "pad.importExport.importSuccessful": "Vellykket!", "pad.importExport.export": "Eksporter aktuelle pad som:", + "pad.importExport.exportetherpad": "Etherpad", "pad.importExport.exporthtml": "HTML", "pad.importExport.exportplain": "Almindelig tekst", "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Du kan kun importere fra almindelig tekst eller HTML-formater. For mere avancerede importfunktioner, installer venligst abiword.", + "pad.importExport.abiword.innerHTML": "Du kan kun importere fra almindelig tekst eller HTML-formater. For mere avancerede importfunktioner, installer AbiWord.", "pad.modals.connected": "Forbundet.", "pad.modals.reconnecting": "Genopretter forbindelsen til din pad...", "pad.modals.forcereconnect": "Gennemtving genoprettelse af forbindelsen", + "pad.modals.reconnecttimer": "Prøver at tilkoble igen", + "pad.modals.cancel": "Afbryd", "pad.modals.userdup": "Åbnet i et andet vindue", "pad.modals.userdup.explanation": "Denne pad synes at være åbnet i mere end ét browservindue på denne computer.", "pad.modals.userdup.advice": "Tilslut igen for at bruge dette vindue i stedet.", @@ -91,6 +97,9 @@ "timeslider.exportCurrent": "Eksporter aktuelle version som:", "timeslider.version": "Version {{version}}", "timeslider.saved": "Gemt den {{day}}.{{month}} {{year}}", + "timeslider.playPause": "Afspil eller sæt padindhold på pause", + "timeslider.backRevision": "Gå en revision tilbage i denne pad", + "timeslider.forwardRevision": "Gå en revision fremad i denne pad", "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", "timeslider.month.january": "januar", "timeslider.month.february": "februar", @@ -106,6 +115,7 @@ "timeslider.month.december": "december", "timeslider.unnamedauthors": "{{num}} {[plural(num) one: unavngiven forfatter, other: unavngivne forfattere]}", "pad.savedrevs.marked": "Denne revision er nu markeret som en gemt revision", + "pad.savedrevs.timeslider": "Du kan se gemte revisioner ved at besøge tidslinjen", "pad.userlist.entername": "Indtast dit navn", "pad.userlist.unnamed": "ikke-navngivet", "pad.userlist.guest": "Gæst", @@ -116,6 +126,7 @@ "pad.impexp.importing": "Importerer...", "pad.impexp.confirmimport": "At importere en fil, vil overskrives den aktuelle pad tekst. Er du sikker på du vil fortsætte?", "pad.impexp.convertFailed": "Vi var ikke i stand til at importere denne fil. Brug et andet dokument-format eller kopier og sæt ind manuelt", + "pad.impexp.padHasData": "Vi kunne ikke importere denne fil, da denne pad allerede har haft ændringer; lav venligst import til en ny pad", "pad.impexp.uploadFailed": "Upload mislykkedes, prøv igen", "pad.impexp.importfailed": "Importen mislykkedes", "pad.impexp.copypaste": "Venligst kopier og sæt ind", diff --git a/src/locales/oc.json b/src/locales/oc.json index 4678de176..5ec80904c 100644 --- a/src/locales/oc.json +++ b/src/locales/oc.json @@ -52,10 +52,12 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Podètz pas importar que de formats tèxte brut o html. Per de foncionalitats d'importacion mai evoluadas, installatz abiword.", + "pad.importExport.abiword.innerHTML": "Podètz pas importar que de formats tèxte brut o html. Per de foncionalitats d'importacion mai evoluadas, installatz abiword.", "pad.modals.connected": "Connectat.", "pad.modals.reconnecting": "Reconnexion cap a vòstre Pad...", "pad.modals.forcereconnect": "Forçar la reconnexion.", + "pad.modals.reconnecttimer": "Ensag de reconnexion", + "pad.modals.cancel": "Anullar", "pad.modals.userdup": "Dobèrt dins una autra fenèstra", "pad.modals.userdup.explanation": "Sembla qu'aqueste Pad es dobèrt dins mai d'una fenèstra de vòstre navigador sus aqueste ordinator.", "pad.modals.userdup.advice": "Se reconnectar en utilizant aquesta fenèstra.", From c62f00477ebbd87286900e747b126559770f2459 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 21 Aug 2017 07:36:39 +0200 Subject: [PATCH 089/102] Localisation updates from https://translatewiki.net. --- src/locales/skr-arab.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/locales/skr-arab.json b/src/locales/skr-arab.json index 5ed2824dd..2123fb6ff 100644 --- a/src/locales/skr-arab.json +++ b/src/locales/skr-arab.json @@ -19,7 +19,7 @@ "pad.settings.language": "زبان:", "pad.importExport.importSuccessful": "کامیاب!", "pad.importExport.exportetherpad": "ایتھرپیڈ", - "pad.importExport.exporthtml": "ایث ٹی ایم ایل", + "pad.importExport.exporthtml": "ایچ ٹی ایم ایل", "pad.importExport.exportplain": "سادہ متن", "pad.importExport.exportword": "مائیکروسافٹ ورڈ", "pad.importExport.exportpdf": "پی ڈی ایف", From a0aedd679301e5bb75cedf889f91e89e8e5014b7 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 31 Aug 2017 07:54:29 +0200 Subject: [PATCH 090/102] Localisation updates from https://translatewiki.net. --- src/locales/bg.json | 9 ++++++++- src/locales/es.json | 2 +- src/locales/skr-arab.json | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/locales/bg.json b/src/locales/bg.json index d1403fe7e..52e424c37 100644 --- a/src/locales/bg.json +++ b/src/locales/bg.json @@ -1,7 +1,8 @@ { "@metadata": { "authors": [ - "Vodnokon4e" + "Vodnokon4e", + "StanProg" ] }, "index.newPad": "Нов пад", @@ -28,8 +29,14 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", + "pad.modals.cancel": "Отказване", "pad.modals.userdup": "Отворен в друг прозорец", + "pad.modals.userdup.explanation": "Изглежда, че този пад е отворен на повече от един раздел в браузъра на компютъра.", + "pad.modals.looping.explanation": "Има проблеми с комуникацията със сървъра за синхронизация.", + "pad.modals.looping.cause": "Може би сте свързани чрез несъвместима защитна стена или прокси.", "pad.modals.initsocketfail": "Сървърът е недостъпен.", + "pad.modals.initsocketfail.explanation": "Свързването със сървъра за синхронизация е неуспешно.", + "pad.modals.initsocketfail.cause": "Това вероятно се дължи на проблем с браузъра Ви или връзката Ви с Интернет.", "pad.modals.slowcommit.explanation": "Сървърът не отговаря.", "pad.modals.slowcommit.cause": "Това може да се дължи на проблеми с мрежовите връзки.", "pad.modals.deleted": "Изтрито.", diff --git a/src/locales/es.json b/src/locales/es.json index 321f15491..cc673e09d 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -92,7 +92,7 @@ "pad.modals.disconnected.explanation": "Se perdió la conexión con el servidor", "pad.modals.disconnected.cause": "El servidor podría no estar disponible. Contacta al administrador del servicio si esto continúa sucediendo.", "pad.share": "Compatir este pad", - "pad.share.readonly": "Sólo lectura", + "pad.share.readonly": "Solo lectura", "pad.share.link": "Enlace", "pad.share.emebdcode": "Incrustar URL", "pad.chat": "Chat", diff --git a/src/locales/skr-arab.json b/src/locales/skr-arab.json index 2123fb6ff..833d341ec 100644 --- a/src/locales/skr-arab.json +++ b/src/locales/skr-arab.json @@ -16,6 +16,7 @@ "pad.wrongPassword": "تہاݙ پاسورڈ غلط ہے", "pad.settings.padSettings": "پیڈ ترتیباں", "pad.settings.fontType": "فونٹ قسم:", + "pad.settings.globalView": "عالمی منظر", "pad.settings.language": "زبان:", "pad.importExport.importSuccessful": "کامیاب!", "pad.importExport.exportetherpad": "ایتھرپیڈ", From 457fdaa36055f496800953c888150308376cc25d Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 7 Sep 2017 07:17:26 +0200 Subject: [PATCH 091/102] Localisation updates from https://translatewiki.net. --- src/locales/eo.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/locales/eo.json b/src/locales/eo.json index 786d3bbed..2754eaf7a 100644 --- a/src/locales/eo.json +++ b/src/locales/eo.json @@ -55,10 +55,12 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Formato “OpenDocument”)", - "pad.importExport.abiword.innerHTML": "Nur kapablas enporti de plata teksto aŭ HTML. Por pli speciala importkapablo, bonvolu instalu la programon, Abiword.", + "pad.importExport.abiword.innerHTML": "Nur kapablas enporti de plata teksto aŭ HTML. Por pli speciala importkapablo, bonvolu instalu la programon, Abiword.", "pad.modals.connected": "Konektita.", "pad.modals.reconnecting": "Rekonektanta al via redaktilo..", "pad.modals.forcereconnect": "Perforte rekonekti", + "pad.modals.reconnecttimer": "Provos rekonekti post", + "pad.modals.cancel": "Nuligi", "pad.modals.userdup": "Malfermita en alia fenestro", "pad.modals.userdup.explanation": "Ĉi tiu teksto ŝajne estas malferma en pli ol unu retumilo sur ĉi tiu komputilo.", "pad.modals.userdup.advice": "Rekonekti por anstataŭe uzi ĉi tiun fenestron.", From 3f875a56e3d84c14d49b9db729f535c024bacb58 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 11 Sep 2017 07:16:33 +0200 Subject: [PATCH 092/102] Localisation updates from https://translatewiki.net. --- src/locales/fa.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/locales/fa.json b/src/locales/fa.json index e1e884188..4b29669e4 100644 --- a/src/locales/fa.json +++ b/src/locales/fa.json @@ -58,10 +58,12 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (قالب سند باز)", - "pad.importExport.abiword.innerHTML": "شما تنها می‌توانید از قالب متن ساده یا اچ‌تی‌ام‌ال درون‌ریزی کنید. برای بیشتر شدن ویژگی‌های درون‌ریزی پیشرفته AbiWord را نصب کنید.", + "pad.importExport.abiword.innerHTML": "شما تنها می‌توانید از قالب متن ساده یا اچ‌تی‌ام‌ال درون‌ریزی کنید. برای بیشتر شدن ویژگی‌های درون‌ریزی پیشرفته AbiWord را نصب کنید.", "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 c7548450c05b61c4232d7aa93926516bfa06688f Mon Sep 17 00:00:00 2001 From: HairyFotr Date: Thu, 14 Sep 2017 13:33:27 +0200 Subject: [PATCH 093/102] Typos and minor fixes in bin, doc, and root --- .gitignore | 1 + CONTRIBUTING.md | 6 +- Makefile | 2 +- README.md | 14 +- bin/buildDebian.sh | 2 +- bin/checkPad.js | 8 +- bin/cleanRun.sh | 4 +- bin/createRelease.sh | 164 ++++++++++----------- bin/debugRun.sh | 6 +- bin/deletePad.js | 4 +- bin/doc/json.js | 4 +- bin/extractPadData.js | 10 +- bin/importSqlFile.js | 2 +- bin/installDeps.sh | 12 +- bin/installOnWindows.bat | 4 +- bin/repairPad.js | 6 +- bin/run.sh | 20 +-- bin/safeRun.sh | 14 +- doc/api/changeset_library.md | 10 +- doc/api/embed_parameters.md | 2 +- doc/api/hooks_server-side.md | 8 +- doc/api/http_api.md | 18 +-- doc/api/pluginfw.md | 2 +- doc/documentation.md | 2 +- doc/easysync/easysync-full-description.tex | 10 +- doc/localization.md | 6 +- doc/plugins.md | 8 +- 27 files changed, 175 insertions(+), 174 deletions(-) diff --git a/.gitignore b/.gitignore index 46773455a..7615acd90 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ npm-debug.log *.key bin/etherpad-1.deb credentials.json +out/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b6e1c2473..09ddc286d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,7 +6,7 @@ * Please be polite, we all are humans and problems can occur. * Please add as much information as possible, for example * client os(s) and version(s) - * browser(s) and version(s), is the problem reproduceable on different clients + * browser(s) and version(s), is the problem reproducible on different clients * special environments like firewalls or antivirus * host os and version * npm and nodejs version @@ -49,7 +49,7 @@ Also, keep it maintainable. We don't wanna end up as the monster Etherpad was! * Make small pull requests that are easy to review but make sure they do add value by themselves / individually ## Coding style -* Do write comments. (You don't have to comment every line, but if you come up with something thats a bit complex/weird, just leave a comment. Bear in mind that you will probably leave the project at some point and that other people will read your code. Undocumented huge amounts of code are worthless!) +* Do write comments. (You don't have to comment every line, but if you come up with something that's a bit complex/weird, just leave a comment. Bear in mind that you will probably leave the project at some point and that other people will read your code. Undocumented huge amounts of code are worthless!) * Never ever use tabs * Indentation: JS/CSS: 2 spaces; HTML: 4 spaces * Don't overengineer. Don't try to solve any possible problem in one step, but try to solve problems as easy as possible and improve the solution over time! @@ -79,7 +79,7 @@ see git flow http://nvie.com/posts/a-successful-git-branching-model/ ### feature branches (in your own repos) * these are the branches where you develop your features in -* If its ready to go out, it will be merged into develop +* If it's ready to go out, it will be merged into develop Over the time we pull features from feature branches into the develop branch. Every month we pull from develop into master. Bugs in master get fixed in hotfix branches. These branches will get merged into master AND develop. There should never be commits in master that aren't in develop diff --git a/Makefile b/Makefile index 25fbf8e87..aedb93724 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ outdoc_files = $(addprefix out/,$(doc_sources:.md=.html)) docassets = $(addprefix out/,$(wildcard doc/assets/*)) -VERSION = $(shell node -e "console.log( require('./src/package.json').version )") +VERSION = $(shell node -e "console.log( require('./src/package.json').version )") UNAME := $(shell uname -s) docs: $(outdoc_files) $(docassets) diff --git a/README.md b/README.md index de1f36199..e54ae18e6 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ that allows your web application to manage pads, users and groups. It is recomme There is also a [jQuery plugin](https://github.com/ether/etherpad-lite-jquery-plugin) that helps you to embed Pads into your website. -There's also a full-featured plugin framework, allowing you to easily add your own features. By default your Etherpad is rather sparse and because Etherpad takes a lot of it's inspiration from Wordpress plugins are really easy to install and update. Once you have Etherpad installed you should visit the plugin page and take control. +There's also a full-featured plugin framework, allowing you to easily add your own features. By default your Etherpad is rather sparse and because Etherpad takes a lot of its inspiration from WordPress, plugins are really easy to install and update. Once you have Etherpad installed you should visit the plugin page and take control. Finally, Etherpad comes with translations into most languages! Users are automatically delivered the correct language for their local settings. @@ -35,7 +35,7 @@ This package works out of the box on any windows machine, but it's not very usef Now, run `start.bat` and open in your browser. You like it? [Next steps](#next-steps). ### Fancy install -You'll need [node.js](http://nodejs.org) and (optionally, though recommended) git. +You'll need [node.js](https://nodejs.org) and (optionally, though recommended) git. 1. Grab the source, either - download @@ -60,7 +60,7 @@ You'll need gzip, git, curl, libssl develop libraries, python and gcc. - *For Fedora/CentOS*: `yum install gzip git curl python openssl-devel && yum groupinstall "Development Tools"` - *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). +Additionally, you'll need [node.js](https://nodejs.org) installed, Ideally the latest stable version, we recommend installing/compiling nodejs from source (avoiding apt). **As any user (we recommend creating a separate user called etherpad):** @@ -92,9 +92,9 @@ Documentation can be found in `docs/`. # Development ## Things you should know -Understand [git](https://training.github.com/) and watch this [video on getting started with Etherpad Development](http://youtu.be/67-Q26YH97E). +Understand [git](https://training.github.com/) and watch this [video on getting started with Etherpad Development](https://youtu.be/67-Q26YH97E). -If you're new to node.js, start with Ryan Dahl's [Introduction to Node.js](http://youtu.be/jo_B4LTHi3I). +If you're new to node.js, start with Ryan Dahl's [Introduction to Node.js](https://youtu.be/jo_B4LTHi3I). You can debug Etherpad using `bin/debugRun.sh`. @@ -108,7 +108,7 @@ Look at the [TODO list](https://github.com/ether/etherpad-lite/wiki/TODO) and ou Also, and most importantly, read our [**Developer Guidelines**](https://github.com/ether/etherpad-lite/blob/master/CONTRIBUTING.md), really! # Get in touch -Join the [mailinglist](http://groups.google.com/group/etherpad-lite-dev) and make some noise on our busy freenode irc channel [#etherpad-lite-dev](http://webchat.freenode.net?channels=#etherpad-lite-dev)! +Join the [mailinglist](https://groups.google.com/group/etherpad-lite-dev) and make some noise on our busy freenode irc channel [#etherpad-lite-dev](https://webchat.freenode.net?channels=#etherpad-lite-dev)! # Modules created for this project @@ -117,7 +117,7 @@ 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](https://flattr.com/thing/71378/Etherpad-Foundation) * Paypal - Press the donate button on [etherpad.org](http://etherpad.org) * [Bitcoin](https://coinbase.com/checkouts/1e572bf8a82e4663499f7f1f66c2d15a) diff --git a/bin/buildDebian.sh b/bin/buildDebian.sh index cc3353c20..58431f738 100755 --- a/bin/buildDebian.sh +++ b/bin/buildDebian.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # IMPORTANT -# Protect agaisnt mispelling a var and rm -rf / +# Protect against misspelling a var and rm -rf / set -u set -e diff --git a/bin/checkPad.js b/bin/checkPad.js index a9b7e8bce..eb45a4b40 100644 --- a/bin/checkPad.js +++ b/bin/checkPad.js @@ -10,7 +10,7 @@ if(process.argv.length != 3) //get the padID var padId = process.argv[2]; -//initalize the variables +//initialize the variables var db, settings, padManager; var npm = require("../src/node_modules/npm"); var async = require("../src/node_modules/async"); @@ -29,7 +29,7 @@ async.series([ settings = require('../src/node/utils/Settings'); db = require('../src/node/db/DB'); - //intallize the database + //initialize the database db.init(callback); }, //get the pad @@ -54,7 +54,7 @@ async.series([ }, function (callback) { - //create an array with key kevisions + //create an array with key revisions //key revisions always save the full pad atext var head = pad.getHeadRevisionNumber(); var keyRevisions = []; @@ -99,7 +99,7 @@ async.series([ process.exit(1); } - //check if there is a atext in the keyRevisions + //check if there is an atext in the keyRevisions if(revisions[keyRev] === undefined || revisions[keyRev].meta === undefined || revisions[keyRev].meta.atext === undefined) { console.error("No atext in key revision " + keyRev); diff --git a/bin/cleanRun.sh b/bin/cleanRun.sh index 55bcf8a75..ef802815d 100755 --- a/bin/cleanRun.sh +++ b/bin/cleanRun.sh @@ -16,7 +16,7 @@ do fi done -#Stop the script if its started as root +#Stop the script if it's started as root if [ "$(id -u)" -eq 0 ] && [ $ignoreRoot -eq 0 ]; then echo "You shouldn't start Etherpad as root!" echo "Please type 'Etherpad rocks my socks' or supply the '--root' argument if you still want to start it as root" @@ -31,7 +31,7 @@ fi #Clean the current environment rm -rf src/node_modules -#Prepare the enviroment +#Prepare the environment bin/installDeps.sh $* || exit 1 #Move to the node folder and start diff --git a/bin/createRelease.sh b/bin/createRelease.sh index 435ec3466..5afced8f2 100755 --- a/bin/createRelease.sh +++ b/bin/createRelease.sh @@ -22,25 +22,25 @@ TMP_DIR="/tmp/" echo "WARNING: You can only run this script if your github api token is allowed to create and merge branches on $ETHER_REPO and $ETHER_WEB_REPO." echo "This script automatically changes the version number in package.json and adds a text to CHANGELOG.md." -echo "When you use this script you should be in the branch that you want to release (develop probably) on latest version. Any changes that are currently not commited will be commited." +echo "When you use this script you should be in the branch that you want to release (develop probably) on latest version. Any changes that are currently not committed will be committed." echo "-----" -# get the latest version +# Get the latest version LATEST_GIT_TAG=$(git tag | tail -n 1) -# current environment +# Current environment echo "Current environment: " echo "- branch: $(git branch | grep '* ')" echo "- last commit date: $(git show --quiet --pretty=format:%ad)" echo "- current version: $LATEST_GIT_TAG" echo "- temp dir: $TMP_DIR" -# get new version number +# Get new version number # format: x.x.x echo -n "Enter new version (x.x.x): " read VERSION -# get the message for the changelogs +# Get the message for the changelogs read -p "Enter new changelog entries (press enter): " tmp=$(mktemp) "${EDITOR:-vi}" $tmp @@ -49,7 +49,7 @@ echo "$changelogText" rm $tmp if [ "$changelogText" != "" ]; then - changelogText="# $VERSION\n$changelogText" + changelogText="# $VERSION\n$changelogText" fi # get the token for the github api @@ -57,114 +57,114 @@ echo -n "Enter your github api token: " read API_TOKEN function check_api_token { - echo "Checking if github api token is valid..." - CURL_RESPONSE=$(curl --silent -i https://api.github.com/user?access_token=$API_TOKEN | iconv -f utf8) - HTTP_STATUS=$(echo $CURL_RESPONSE | head -1 | sed -r 's/.* ([0-9]{3}) .*/\1/') - [[ $HTTP_STATUS != "200" ]] && echo "Aborting: Invalid github api token" && exit 1 + echo "Checking if github api token is valid..." + CURL_RESPONSE=$(curl --silent -i https://api.github.com/user?access_token=$API_TOKEN | iconv -f utf8) + HTTP_STATUS=$(echo $CURL_RESPONSE | head -1 | sed -r 's/.* ([0-9]{3}) .*/\1/') + [[ $HTTP_STATUS != "200" ]] && echo "Aborting: Invalid github api token" && exit 1 } function modify_files { - # Add changelog text to first line of CHANGELOG.md - sed -i "1s/^/${changelogText}\n/" CHANGELOG.md - # Replace version number of etherpad in package.json - sed -i -r "s/(\"version\"[ ]*: \").*(\")/\1$VERSION\2/" src/package.json + # Add changelog text to first line of CHANGELOG.md + sed -i "1s/^/${changelogText}\n/" CHANGELOG.md + # Replace version number of etherpad in package.json + sed -i -r "s/(\"version\"[ ]*: \").*(\")/\1$VERSION\2/" src/package.json } function create_release_branch { - echo "Creating new release branch..." - git rev-parse --verify release/$VERSION 2>/dev/null - if [ $? == 0 ]; then - echo "Aborting: Release branch already present" - exit 1 - fi - git checkout -b release/$VERSION - [[ $? != 0 ]] && echo "Aborting: Error creating relase branch" && exit 1 + echo "Creating new release branch..." + git rev-parse --verify release/$VERSION 2>/dev/null + if [ $? == 0 ]; then + echo "Aborting: Release branch already present" + exit 1 + fi + git checkout -b release/$VERSION + [[ $? != 0 ]] && echo "Aborting: Error creating release branch" && exit 1 - echo "Commiting CHANGELOG.md and package.json" - git add CHANGELOG.md - git add src/package.json - git commit -m "Release version $VERSION" + echo "Committing CHANGELOG.md and package.json" + git add CHANGELOG.md + git add src/package.json + git commit -m "Release version $VERSION" - echo "Pushing release branch to github..." - git push -u $ETHER_REPO release/$VERSION - [[ $? != 0 ]] && echo "Aborting: Error pushing release branch to github" && exit 1 + echo "Pushing release branch to github..." + git push -u $ETHER_REPO release/$VERSION + [[ $? != 0 ]] && echo "Aborting: Error pushing release branch to github" && exit 1 } function merge_release_branch { - echo "Merging release to master branch on github..." - API_JSON=$(printf '{"base": "master","head": "release/%s","commit_message": "Merge new release into master branch!"}' $VERSION) - CURL_RESPONSE=$(curl --silent -i -N --data "$API_JSON" https://api.github.com/repos/ether/etherpad-lite/merges?access_token=$API_TOKEN | iconv -f utf8) - echo $CURL_RESPONSE - HTTP_STATUS=$(echo $CURL_RESPONSE | head -1 | sed -r 's/.* ([0-9]{3}) .*/\1/') - [[ $HTTP_STATUS != "200" ]] && echo "Aborting: Error merging release branch on github" && exit 1 + echo "Merging release to master branch on github..." + API_JSON=$(printf '{"base": "master","head": "release/%s","commit_message": "Merge new release into master branch!"}' $VERSION) + CURL_RESPONSE=$(curl --silent -i -N --data "$API_JSON" https://api.github.com/repos/ether/etherpad-lite/merges?access_token=$API_TOKEN | iconv -f utf8) + echo $CURL_RESPONSE + HTTP_STATUS=$(echo $CURL_RESPONSE | head -1 | sed -r 's/.* ([0-9]{3}) .*/\1/') + [[ $HTTP_STATUS != "200" ]] && echo "Aborting: Error merging release branch on github" && exit 1 } function create_builds { - echo "Cloning etherpad-lite repo and ether.github.com repo..." - cd $TMP_DIR - rm -rf etherpad-lite ether.github.com - git clone $ETHER_REPO --branch master - git clone $ETHER_WEB_REPO - echo "Creating windows build..." - cd etherpad-lite - bin/buildForWindows.sh - [[ $? != 0 ]] && echo "Aborting: Error creating build for windows" && exit 1 - echo "Creating docs..." - make docs - [[ $? != 0 ]] && echo "Aborting: Error generating docs" && exit 1 + echo "Cloning etherpad-lite repo and ether.github.com repo..." + cd $TMP_DIR + rm -rf etherpad-lite ether.github.com + git clone $ETHER_REPO --branch master + git clone $ETHER_WEB_REPO + echo "Creating windows build..." + cd etherpad-lite + bin/buildForWindows.sh + [[ $? != 0 ]] && echo "Aborting: Error creating build for windows" && exit 1 + echo "Creating docs..." + make docs + [[ $? != 0 ]] && echo "Aborting: Error generating docs" && exit 1 } function push_builds { - cd $TMP_DIR/etherpad-lite/ - echo "Copying windows build and docs to website repo..." - GIT_SHA=$(git rev-parse HEAD | cut -c1-10) - mv etherpad-lite-win.zip $TMP_DIR/ether.github.com/downloads/etherpad-lite-win-$VERSION-$GIT_SHA.zip + cd $TMP_DIR/etherpad-lite/ + echo "Copying windows build and docs to website repo..." + GIT_SHA=$(git rev-parse HEAD | cut -c1-10) + mv etherpad-lite-win.zip $TMP_DIR/ether.github.com/downloads/etherpad-lite-win-$VERSION-$GIT_SHA.zip - mv out/doc $TMP_DIR/ether.github.com/doc/v$VERSION + mv out/doc $TMP_DIR/ether.github.com/doc/v$VERSION - cd $TMP_DIR/ether.github.com/ - sed -i "s/etherpad-lite-win.*\.zip/etherpad-lite-win-$VERSION-$GIT_SHA.zip/" index.html - sed -i "s/$LATEST_GIT_TAG/$VERSION/g" index.html - git checkout -b release_$VERSION - [[ $? != 0 ]] && echo "Aborting: Error creating new release branch" && exit 1 - git add doc/ - git add downloads/ - git commit -a -m "Release version $VERSION" - git push -u $ETHER_WEB_REPO release_$VERSION - [[ $? != 0 ]] && echo "Aborting: Error pushing release branch to github" && exit 1 + cd $TMP_DIR/ether.github.com/ + sed -i "s/etherpad-lite-win.*\.zip/etherpad-lite-win-$VERSION-$GIT_SHA.zip/" index.html + sed -i "s/$LATEST_GIT_TAG/$VERSION/g" index.html + git checkout -b release_$VERSION + [[ $? != 0 ]] && echo "Aborting: Error creating new release branch" && exit 1 + git add doc/ + git add downloads/ + git commit -a -m "Release version $VERSION" + git push -u $ETHER_WEB_REPO release_$VERSION + [[ $? != 0 ]] && echo "Aborting: Error pushing release branch to github" && exit 1 } function merge_web_branch { echo "Merging release to master branch on github..." API_JSON=$(printf '{"base": "master","head": "release_%s","commit_message": "Release version %s"}' $VERSION $VERSION) - CURL_RESPONSE=$(curl --silent -i -N --data "$API_JSON" https://api.github.com/repos/ether/ether.github.com/merges?access_token=$API_TOKEN | iconv -f utf8) - echo $CURL_RESPONSE - HTTP_STATUS=$(echo $CURL_RESPONSE | head -1 | sed -r 's/.* ([0-9]{3}) .*/\1/') - [[ $HTTP_STATUS != "200" ]] && echo "Aborting: Error merging release branch" && exit 1 + CURL_RESPONSE=$(curl --silent -i -N --data "$API_JSON" https://api.github.com/repos/ether/ether.github.com/merges?access_token=$API_TOKEN | iconv -f utf8) + echo $CURL_RESPONSE + HTTP_STATUS=$(echo $CURL_RESPONSE | head -1 | sed -r 's/.* ([0-9]{3}) .*/\1/') + [[ $HTTP_STATUS != "200" ]] && echo "Aborting: Error merging release branch" && exit 1 } function publish_release { - echo -n "Do you want to publish a new release on github (y/n)? " - read PUBLISH_RELEASE - if [ $PUBLISH_RELEASE = "y" ]; then - # create a new release on github - API_JSON=$(printf '{"tag_name": "%s","target_commitish": "master","name": "Release %s","body": "%s","draft": false,"prerelease": false}' $VERSION $VERSION $changelogText) - CURL_RESPONSE=$(curl --silent -i -N --data "$API_JSON" https://api.github.com/repos/ether/etherpad-lite/releases?access_token=$API_TOKEN | iconv -f utf8) - HTTP_STATUS=$(echo $CURL_RESPONSE | head -1 | sed -r 's/.* ([0-9]{3}) .*/\1/') - [[ $HTTP_STATUS != "201" ]] && echo "Aborting: Error publishing release on github" && exit 1 - else - echo "No release published on github!" - fi + echo -n "Do you want to publish a new release on github (y/n)? " + read PUBLISH_RELEASE + if [ $PUBLISH_RELEASE = "y" ]; then + # create a new release on github + API_JSON=$(printf '{"tag_name": "%s","target_commitish": "master","name": "Release %s","body": "%s","draft": false,"prerelease": false}' $VERSION $VERSION $changelogText) + CURL_RESPONSE=$(curl --silent -i -N --data "$API_JSON" https://api.github.com/repos/ether/etherpad-lite/releases?access_token=$API_TOKEN | iconv -f utf8) + HTTP_STATUS=$(echo $CURL_RESPONSE | head -1 | sed -r 's/.* ([0-9]{3}) .*/\1/') + [[ $HTTP_STATUS != "201" ]] && echo "Aborting: Error publishing release on github" && exit 1 + else + echo "No release published on github!" + fi } function todo_notification { - echo "Release procedure was successful, but you have to do some steps manually:" - echo "- Update the wiki at https://github.com/ether/etherpad-lite/wiki" - echo "- Create a pull request on github to merge the master branch back to develop" - echo "- Announce the new release on the mailing list, blog.etherpad.org and Twitter" + echo "Release procedure was successful, but you have to do some steps manually:" + echo "- Update the wiki at https://github.com/ether/etherpad-lite/wiki" + echo "- Create a pull request on github to merge the master branch back to develop" + echo "- Announce the new release on the mailing list, blog.etherpad.org and Twitter" } -# call functions +# Call functions check_api_token modify_files create_release_branch diff --git a/bin/debugRun.sh b/bin/debugRun.sh index f90009d05..b42112f7f 100755 --- a/bin/debugRun.sh +++ b/bin/debugRun.sh @@ -8,7 +8,7 @@ if [ -d "../bin" ]; then cd "../" fi -#prepare the enviroment +#Prepare the environment bin/installDeps.sh || exit 1 hash node-inspector > /dev/null 2>&1 || { @@ -20,9 +20,9 @@ hash node-inspector > /dev/null 2>&1 || { node-inspector & -echo "If you are new to node-inspector, take a look at this video: http://youtu.be/AOnK3NVnxL8" +echo "If you are new to node-inspector, take a look at this video: https://youtu.be/AOnK3NVnxL8" node --debug node_modules/ep_etherpad-lite/node/server.js $* -#kill node-inspector before ending +#Kill node-inspector before ending kill $! diff --git a/bin/deletePad.js b/bin/deletePad.js index f7a6d2038..fe7761db0 100644 --- a/bin/deletePad.js +++ b/bin/deletePad.js @@ -37,12 +37,12 @@ async.series([ db = require('../src/node/db/DB'); callback(); }, - // intallize the database + // initialize the database function (callback) { db.init(callback); }, - // delete the pad and it's links + // delete the pad and its links function (callback) { padManager = require('../src/node/db/PadManager'); diff --git a/bin/doc/json.js b/bin/doc/json.js index 2459bc26a..a404675b5 100644 --- a/bin/doc/json.js +++ b/bin/doc/json.js @@ -96,7 +96,7 @@ function doJSON(input, filename, cb) { // a list: starting with list_start, ending with list_end, // maybe containing other nested lists in each item. // - // If one of these isnt' found, then anything that comes between + // If one of these isn't found, then anything that comes between // here and the next heading should be parsed as the desc. var stability if (state === 'AFTERHEADING') { @@ -198,7 +198,7 @@ function processList(section) { var current; var stack = []; - // for now, *just* build the heirarchical list + // for now, *just* build the hierarchical list list.forEach(function(tok) { var type = tok.type; if (type === 'space') return; diff --git a/bin/extractPadData.js b/bin/extractPadData.js index e3678c4e0..419082497 100644 --- a/bin/extractPadData.js +++ b/bin/extractPadData.js @@ -1,5 +1,5 @@ /* - This is a debug tool. It helps to extract all datas of a pad and move it from an productive enviroment and to a develop enviroment to reproduce bugs there. It outputs a dirtydb file + This is a debug tool. It helps to extract all datas of a pad and move it from an productive environment and to a develop environment to reproduce bugs there. It outputs a dirtydb file */ if(process.argv.length != 3) @@ -38,7 +38,7 @@ async.series([ dirty = require("../node_modules/ep_etherpad-lite/node_modules/ueberDB/node_modules/dirty")(padId + ".db"); callback(); }, - //intallize the database + //initialize the database function (callback) { db.init(callback); @@ -85,7 +85,7 @@ async.series([ if(err) { callback(err); return} if(dbvalue && typeof dbvalue != 'object'){ - dbvalue=JSON.parse(dbvalue); // if its not json then parse it as json + dbvalue=JSON.parse(dbvalue); // if it's not json then parse it as json } dirty.set(dbkey, dbvalue, callback); @@ -105,5 +105,5 @@ async.series([ //get the pad object //get all revisions of this pad //get all authors related to this pad -//get the readonly link releated to this pad -//get the chat entrys releated to this pad +//get the readonly link related to this pad +//get the chat entries related to this pad diff --git a/bin/importSqlFile.js b/bin/importSqlFile.js index 6491cbea1..5cdf46e5d 100644 --- a/bin/importSqlFile.js +++ b/bin/importSqlFile.js @@ -30,7 +30,7 @@ require("ep_etherpad-lite/node_modules/npm").load({}, function(er,npm) { //there was an error while initializing the database, output it and stop if(err) { - console.error("ERROR: Problem while initalizing the database"); + console.error("ERROR: Problem while initializing the database"); console.error(err.stack ? err.stack : err); process.exit(1); } diff --git a/bin/installDeps.sh b/bin/installDeps.sh index 48a34905d..5ccba46dd 100755 --- a/bin/installDeps.sh +++ b/bin/installDeps.sh @@ -23,19 +23,19 @@ hash curl > /dev/null 2>&1 || { } #Is node installed? -#not checking io.js, default installation creates a symbolic link to node +#Not checking io.js, default installation creates a symbolic link to node hash node > /dev/null 2>&1 || { - echo "Please install node.js ( http://nodejs.org )" >&2 + echo "Please install node.js ( https://nodejs.org )" >&2 exit 1 } #Is npm installed? hash npm > /dev/null 2>&1 || { - echo "Please install npm ( http://npmjs.org )" >&2 + echo "Please install npm ( https://npmjs.org )" >&2 exit 1 } -#check npm version +#Check npm version NPM_VERSION=$(npm --version) NPM_MAIN_VERSION=$(echo $NPM_VERSION | cut -d "." -f 1) if [ $(echo $NPM_MAIN_VERSION) = "0" ]; then @@ -43,7 +43,7 @@ if [ $(echo $NPM_MAIN_VERSION) = "0" ]; then exit 1 fi -#check node version +#Check node version NODE_VERSION=$(node --version) NODE_V_MINOR=$(echo $NODE_VERSION | cut -d "." -f 1-2) NODE_V_MAIN=$(echo $NODE_VERSION | cut -d "." -f 1) @@ -61,7 +61,7 @@ for arg in $*; do a=$arg done -#Does a $settings exist? if no copy the template +#Does a $settings exist? if not copy the template if [ ! -f $settings ]; then echo "Copy the settings template to $settings..." cp settings.json.template $settings || exit 1 diff --git a/bin/installOnWindows.bat b/bin/installOnWindows.bat index 89fa335d8..db679ef08 100644 --- a/bin/installOnWindows.bat +++ b/bin/installOnWindows.bat @@ -1,10 +1,10 @@ @echo off -:: change directory to etherpad-lite root +:: Change directory to etherpad-lite root cd /D "%~dp0\.." :: Is node installed? -cmd /C node -e "" || ( echo "Please install node.js ( http://nodejs.org )" && exit /B 1 ) +cmd /C node -e "" || ( echo "Please install node.js ( https://nodejs.org )" && exit /B 1 ) echo _ echo Ensure that all dependencies are up to date... If this is the first time you have run Etherpad please be patient. diff --git a/bin/repairPad.js b/bin/repairPad.js index 4a90812c2..28f28cb6e 100644 --- a/bin/repairPad.js +++ b/bin/repairPad.js @@ -39,7 +39,7 @@ async.series([ db = require('../src/node/db/DB'); callback(); }, - //intallize the database + //initialize the database function (callback) { db.init(callback); @@ -101,6 +101,6 @@ async.series([ //get the pad object //get all revisions of this pad //get all authors related to this pad -//get the readonly link releated to this pad -//get the chat entrys releated to this pad +//get the readonly link related to this pad +//get the chat entries related to this pad //remove all keys from database and insert them again diff --git a/bin/run.sh b/bin/run.sh index c50845ec9..b80494791 100755 --- a/bin/run.sh +++ b/bin/run.sh @@ -16,19 +16,19 @@ do fi done -#Stop the script if its started as root +#Stop the script if it's started as root if [ "$(id -u)" -eq 0 ] && [ $ignoreRoot -eq 0 ]; then - echo "You shouldn't start Etherpad as root!" - echo "Please type 'Etherpad rocks my socks' or supply the '--root' argument if you still want to start it as root" - read rocks - if [ ! "$rocks" == "Etherpad rocks my socks" ] - then - echo "Your input was incorrect" - exit 1 - fi + echo "You shouldn't start Etherpad as root!" + echo "Please type 'Etherpad rocks my socks' or supply the '--root' argument if you still want to start it as root" + read rocks + if [ ! "$rocks" == "Etherpad rocks my socks" ] + then + echo "Your input was incorrect" + exit 1 + fi fi -#prepare the enviroment +#Prepare the environment bin/installDeps.sh $* || exit 1 #Move to the node folder and start diff --git a/bin/safeRun.sh b/bin/safeRun.sh index 519a0b6ef..d024f0b27 100755 --- a/bin/safeRun.sh +++ b/bin/safeRun.sh @@ -6,10 +6,10 @@ # 0 silent # 1 email ERROR_HANDLING=0 -# Your email address which should recieve the error messages +# Your email address which should receive the error messages EMAIL_ADDRESS="no-reply@example.com" -# Sets the minimun amount of time betweens the sending of error emails. -# This ensures you not get spamed while a endless reboot loop +# Sets the minimum amount of time between the sending of error emails. +# This ensures you do not get spammed during an endless reboot loop # It's the time in seconds TIME_BETWEEN_EMAILS=600 # 10 minutes @@ -26,7 +26,7 @@ if [ -d "../bin" ]; then cd "../" fi -#check if a logfile parameter is set +#Check if a logfile parameter is set if [ -z "${LOG}" ]; then echo "Set a logfile as the first parameter" exit 1 @@ -35,18 +35,18 @@ fi shift while [ 1 ] do - #try to touch the file if it doesn't exist + #Try to touch the file if it doesn't exist if [ ! -f ${LOG} ]; then touch ${LOG} || ( echo "Logfile '${LOG}' is not writeable" && exit 1 ) fi - #check if the file is writeable + #Check if the file is writeable if [ ! -w ${LOG} ]; then echo "Logfile '${LOG}' is not writeable" exit 1 fi - #start the application + #Start the application bin/run.sh $@ >>${LOG} 2>>${LOG} #Send email diff --git a/doc/api/changeset_library.md b/doc/api/changeset_library.md index 2dce55aa3..3bb4f055a 100644 --- a/doc/api/changeset_library.md +++ b/doc/api/changeset_library.md @@ -4,15 +4,15 @@ "Z:z>1|2=m=b*0|1+1$\n" ``` -This is a Changeset. Its just a string and its very difficult to read in this form. But the Changeset Library gives us some tools to read it. +This is a Changeset. It's just a string and it's very difficult to read in this form. But the Changeset Library gives us some tools to read it. -A changeset describes the diff between two revisions of the document. The Browser sends changesets to the server and the server sends them to the clients to update them. This Changesets gets also saved into the history of a pad. Which allows us to go back to every revision from the past. +A changeset describes the diff between two revisions of the document. The Browser sends changesets to the server and the server sends them to the clients to update them. These Changesets also get saved into the history of a pad. This allows us to go back to every revision from the past. ## Changeset.unpack(changeset) * `changeset` {String} -This functions returns an object representaion of the changeset, similar to this: +This function returns an object representation of the changeset, similar to this: ``` { oldLen: 35, newLen: 36, ops: '|2=m=b*0|1+1', charBank: '\n' } @@ -65,7 +65,7 @@ There are 3 types of operators: `+`,`-` and `=`. These operators describe differ fromJsonable: [Function] } ``` -This creates an empty apool. A apool saves which attributes were used during the history of a pad. There is one apool for each pad. It only saves the attributes that were really used, it doesn't save unused attributes. Lets fill this apool with some values +This creates an empty apool. An apool saves which attributes were used during the history of a pad. There is one apool for each pad. It only saves the attributes that were really used, it doesn't save unused attributes. Let's fill this apool with some values ``` > apool.fromJsonable({"numToAttrib":{"0":["author","a.kVnWeomPADAT2pn9"],"1":["bold","true"],"2":["italic","true"]},"nextNum":3}); @@ -88,7 +88,7 @@ This creates an empty apool. A apool saves which attributes were used during the fromJsonable: [Function] } ``` -We used the fromJsonable function to fill the empty apool with values. the fromJsonable and toJsonable functions are used to serialize and deserialize an apool. You can see that it stores the relation between numbers and attributes. So for example the attribute 1 is the attribute bold and vise versa. A attribute is always a key value pair. For stuff like bold and italic its just 'italic':'true'. For authors its author:$AUTHORID. So a character can be bold and italic. But it can't belong to multiple authors +We used the fromJsonable function to fill the empty apool with values. the fromJsonable and toJsonable functions are used to serialize and deserialize an apool. You can see that it stores the relation between numbers and attributes. So for example the attribute 1 is the attribute bold and vise versa. An attribute is always a key value pair. For stuff like bold and italic it's just 'italic':'true'. For authors it's author:$AUTHORID. So a character can be bold and italic. But it can't belong to multiple authors ``` > apool.getAttrib(1) diff --git a/doc/api/embed_parameters.md b/doc/api/embed_parameters.md index dcbe3e5b3..ea225d842 100644 --- a/doc/api/embed_parameters.md +++ b/doc/api/embed_parameters.md @@ -1,5 +1,5 @@ # Embed parameters -You can easily embed your etherpad-lite into any webpage by using iframes. You can configure the embedded pad using embed paramters. +You can easily embed your etherpad-lite into any webpage by using iframes. You can configure the embedded pad using embed parameters. Example: diff --git a/doc/api/hooks_server-side.md b/doc/api/hooks_server-side.md index d4e836404..5dc8f0945 100644 --- a/doc/api/hooks_server-side.md +++ b/doc/api/hooks_server-side.md @@ -125,7 +125,7 @@ Things in context: 1. pad - the pad instance -This hook gets called when an pad was loaded. If a new pad was created and loaded this event will be emitted too. +This hook gets called when a pad was loaded. If a new pad was created and loaded this event will be emitted too. ## padUpdate Called from: src/node/db/Pad.js @@ -219,7 +219,7 @@ Things in context: 1. message - the message being handled 2. client - the client object from socket.io -This hook will be called once a message arrive. If a plugin calls `callback(null)` the message will be dropped. However it is not possible to modify the message. +This hook will be called once a message arrive. If a plugin calls `callback(null)` the message will be dropped. However, it is not possible to modify the message. Plugins may also decide to implement custom behavior once a message arrives. @@ -272,7 +272,7 @@ Things in context: 1. clientVars - the basic `clientVars` built by the core 2. pad - the pad this session is about -This hook will be called once a client connects and the `clientVars` are being sent. Plugins can use this hook to give the client a initial configuriation, like the tracking-id of an external analytics-tool that is used on the client-side. You can also overwrite values from the original `clientVars`. +This hook will be called once a client connects and the `clientVars` are being sent. Plugins can use this hook to give the client an initial configuration, like the tracking-id of an external analytics-tool that is used on the client-side. You can also overwrite values from the original `clientVars`. Example: @@ -397,7 +397,7 @@ Things in context: 1. Pad object -Identical to `exportHtmlAdditionalTags`, but for tags that are stored with an specific value (not simply `true`) on the attribute pool. For example `['color', 'red']`, instead of `['bold', true]`. This hook will allow a plug-in developer to include more properties and attributes to support during HTML Export. An Array of arrays should be returned. The exported HTML will contain tags like `` for the content where attributes are `['color', 'red']`. +Identical to `exportHtmlAdditionalTags`, but for tags that are stored with a specific value (not simply `true`) on the attribute pool. For example `['color', 'red']`, instead of `['bold', true]`. This hook will allow a plug-in developer to include more properties and attributes to support during HTML Export. An Array of arrays should be returned. The exported HTML will contain tags like `` for the content where attributes are `['color', 'red']`. Example: ``` diff --git a/doc/api/http_api.md b/doc/api/http_api.md index 4b6ea50e8..cacefb532 100644 --- a/doc/api/http_api.md +++ b/doc/api/http_api.md @@ -86,19 +86,19 @@ Responses are valid JSON in the following format: * **2** internal error * **3** no such function * **4** no or wrong API Key -* **message** a status message. Its ok if everything is fine, else it contains an error message +* **message** a status message. It's ok if everything is fine, else it contains an error message * **data** the payload ### Overview -![API Overview](http://i.imgur.com/d0nWp.png) +![API Overview](https://i.imgur.com/d0nWp.png) ## Data Types * **groupID** a string, the unique id of a group. Format is g.16RANDOMCHARS, for example g.s8oes9dhwrvt0zif * **sessionID** a string, the unique id of a session. Format is s.16RANDOMCHARS, for example s.s8oes9dhwrvt0zif * **authorID** a string, the unique id of an author. Format is a.16RANDOMCHARS, for example a.s8oes9dhwrvt0zif -* **readOnlyID** a string, the unique id of an readonly relation to a pad. Format is r.16RANDOMCHARS, for example r.s8oes9dhwrvt0zif +* **readOnlyID** a string, the unique id of a readonly relation to a pad. Format is r.16RANDOMCHARS, for example r.s8oes9dhwrvt0zif * **padID** a string, format is GROUPID$PADNAME, for example the pad test of group g.s8oes9dhwrvt0zif has padID g.s8oes9dhwrvt0zif$test ### Authentication @@ -107,14 +107,14 @@ Authentication works via a token that is sent with each request as a post parame ### Node Interoperability -All functions will also be available through a node module accessable from other node.js applications. +All functions will also be available through a node module accessible from other node.js applications. ### JSONP The API provides _JSONP_ support to allow requests from a server in a different domain. Simply add `&jsonp=?` to the API call. -Example usage: http://api.jquery.com/jQuery.getJSON/ +Example usage: https://api.jquery.com/jQuery.getJSON/ ## API Methods @@ -213,7 +213,7 @@ Returns the Author Name of the author -> can't be deleted cause this would involve scanning all the pads where this author was ### Session -Sessions can be created between a group and an author. This allows an author to access more than one group. The sessionID will be set as a cookie to the client and is valid until a certain date. The session cookie can also contain multiple comma-seperated sessionIDs, allowing a user to edit pads in different groups at the same time. Only users with a valid session for this group, can access group pads. You can create a session after you authenticated the user at your web application, to give them access to the pads. You should save the sessionID of this session and delete it after the user logged out. +Sessions can be created between a group and an author. This allows an author to access more than one group. The sessionID will be set as a cookie to the client and is valid until a certain date. The session cookie can also contain multiple comma-separated sessionIDs, allowing a user to edit pads in different groups at the same time. Only users with a valid session for this group, can access group pads. You can create a session after you authenticated the user at your web application, to give them access to the pads. You should save the sessionID of this session and delete it after the user logged out. #### createSession(groupID, authorID, validUntil) * API >= 1 @@ -307,7 +307,7 @@ returns the text of a pad formatted as HTML #### setHTML(padID, html) * API >= 1 -sets the text of a pad based on HTML, HTML must be well formed. Malformed HTML will send a warning to the API log. +sets the text of a pad based on HTML, HTML must be well-formed. Malformed HTML will send a warning to the API log. *Example returns:* * `{code: 0, message:"ok", data: null}` @@ -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 it's forbidden for normal pads to include a $ in the name. #### createPad(padID [, text]) * API >= 1 @@ -543,7 +543,7 @@ return true of false #### setPassword(padID, password) * API >= 1 -returns ok or a error message +returns ok or an error message *Example returns:* * `{code: 0, message:"ok", data: null}` diff --git a/doc/api/pluginfw.md b/doc/api/pluginfw.md index 2189c74ca..7e0499c30 100644 --- a/doc/api/pluginfw.md +++ b/doc/api/pluginfw.md @@ -3,7 +3,7 @@ ## plugins.update `require("ep_etherpad-lite/static/js/plugingfw/plugins").update()` will use npm to list all installed modules and read their ep.json files, registering the contained hooks. -A hook registration is a pairs of a hook name and a function reference (filename for require() plus function name) +A hook registration is a pair of a hook name and a function reference (filename for require() plus function name) ## hooks.callAll `require("ep_etherpad-lite/static/js/plugingfw/hooks").callAll("hook_name", {argname:value})` will call all hook functions registered for `hook_name` with `{argname:value}`. diff --git a/doc/documentation.md b/doc/documentation.md index ba4dc61f0..307c38af8 100644 --- a/doc/documentation.md +++ b/doc/documentation.md @@ -10,6 +10,6 @@ provided to event handlers are detailed in a list underneath the topic heading. Every `.html` file is generated based on the corresponding -`.markdown` file in the `doc/api/` folder in the source tree. The +`.md` file in the `doc/api/` folder in the source tree. The documentation is generated using the `bin/doc/generate.js` program. The HTML template is located at `doc/template.html`. diff --git a/doc/easysync/easysync-full-description.tex b/doc/easysync/easysync-full-description.tex index 5ed9f29e3..5c936b277 100644 --- a/doc/easysync/easysync-full-description.tex +++ b/doc/easysync/easysync-full-description.tex @@ -85,7 +85,7 @@ For any two changesets $A$, $B$ such that \item[] $A=(n_1\rightarrow n_2)[\cdots]$ \item[] $B=(n_2\rightarrow n_3)[\cdots]$ \end{itemize} -it is clear that there is a third changeset $C=(n_1\rightarrow n_3)[\cdots]$ such that applying $C$ to a document $X$ yeilds the same resulting document as does applying $A$ and then $B$. In this case, we write $AB=C$. +it is clear that there is a third changeset $C=(n_1\rightarrow n_3)[\cdots]$ such that applying $C$ to a document $X$ yields the same resulting document as does applying $A$ and then $B$. In this case, we write $AB=C$. Given the representation from Section \ref{representation}, it is straightforward to compute the composition of two changesets. @@ -93,9 +93,9 @@ Given the representation from Section \ref{representation}, it is straightforwar Now we come to realtime document editing. Suppose two different users make two different changes to the same document at the same time. It is impossible to compose these changes. For example, if we have the document $X$ of length $n$, we may have $A=(n\rightarrow n_a)[\ldots n_a \mathrm{characters}]$, $B=(n\rightarrow n_b)[\ldots n_b \mathrm{characters}]$ where $n\neq n_a\neq n_b$. -It is impossible to compute $(XA)B$ because $B$ can only be applied to a document of length $n$, and $(XA)$ has length $n_a$. Similarly, $A$ cannot be appliet to $(XB)$ because $(XB)$ has length $n_b$. +It is impossible to compute $(XA)B$ because $B$ can only be applied to a document of length $n$, and $(XA)$ has length $n_a$. Similarly, $A$ cannot be applied to $(XB)$ because $(XB)$ has length $n_b$. -This is where \emph{merging} comes in. Merging takes two changesets that apply to the same initial document (and that cannot be composed), and computes a single new changeset that presevers the intent of both changes. The merge of $A$ and $B$ is written as $m(A,B)$. For the Etherpad system to work, we require that $m(A,B)=m(B,A)$. +This is where \emph{merging} comes in. Merging takes two changesets that apply to the same initial document (and that cannot be composed), and computes a single new changeset that preserves the intent of both changes. The merge of $A$ and $B$ is written as $m(A,B)$. For the Etherpad system to work, we require that $m(A,B)=m(B,A)$. Aside from what we have said so far about merging, there are many different implementations that will lead to a workable system. We have created one implementation for text that has the following constraints. @@ -156,7 +156,7 @@ server always. (This may distinguish from prior art?) The other critical design feature of the system is that \emph{A client must always be able to edit their local copy of the document, so the user is never blocked from - typing because of waiting to to send or receive data.} + typing because of waiting to send or receive data.} \section{Client State} @@ -329,7 +329,7 @@ with: \end{enumerate} \subsection{Respond to client connect} -When a server recieves a connection request from a client, +When a server receives a connection request from a client, it receives the client's unique ID and stores that in the server's set of connected clients. It then sends the client the contents of HEADTEXT, and the corresponding diff --git a/doc/localization.md b/doc/localization.md index 4fb9a0472..ba247ea35 100644 --- a/doc/localization.md +++ b/doc/localization.md @@ -3,9 +3,9 @@ Etherpad provides a multi-language user interface, that's apart from your users' ## Translating -We rely on http://translatewiki.net to handle the translation process for us, so if you'd like to help... +We rely on https://translatewiki.net to handle the translation process for us, so if you'd like to help... -1. sign up at http://translatewiki.net +1. Sign up at https://translatewiki.net 2. Visit our [TWN project page](https://translatewiki.net/wiki/Translating:Etherpad_lite) 3. Click on `Translate Etherpad lite interface` 4. Choose a target language, you'd like to translate our interface to, and hit `Fetch` @@ -62,7 +62,7 @@ alert(window._('pad.chat')); ``` ### 2. Create translate files in the locales directory of your plugin -* The name of the file must be the language code of the language it contains translations for (see [supported lang codes](http://joker-x.github.com/languages4translatewiki/test/); e.g. en ? English, es ? Spanish...) +* The name of the file must be the language code of the language it contains translations for (see [supported lang codes](https://joker-x.github.com/languages4translatewiki/test/); e.g. en ? English, es ? Spanish...) * The extension of the file must be `.json` * The default language is English, so your plugin should always provide `en.json` * In order to avoid naming conflicts, your message keys should start with the name of your plugin followed by a dot (see below) diff --git a/doc/plugins.md b/doc/plugins.md index 76c409b17..e5b004087 100644 --- a/doc/plugins.md +++ b/doc/plugins.md @@ -1,7 +1,7 @@ # Plugins Etherpad allows you to extend its functionality with plugins. A plugin registers hooks (functions) for certain events (thus certain features) in Etherpad-lite to execute its own functionality based on these events. -Publicly available plugins can be found in the npm registry (see ). Etherpad-lite's naming convention for plugins is to prefix your plugins with `ep_`. So, e.g. it's `ep_flubberworms`. Thus you can install plugins from npm, using `npm install ep_flubberworm` in etherpad-lite's root directory. +Publicly available plugins can be found in the npm registry (see ). Etherpad-lite's naming convention for plugins is to prefix your plugins with `ep_`. So, e.g. it's `ep_flubberworms`. Thus you can install plugins from npm, using `npm install ep_flubberworm` in etherpad-lite's root directory. You can also browse to `http://yourEtherpadInstan.ce/admin/plugins`, which will list all installed plugins and those available on npm. It even provides functionality to search through all available plugins. @@ -17,7 +17,7 @@ ep_/ ``` If your plugin includes client-side hooks, put them in `static/js/`. If you're adding in CSS or image files, you should put those files in `static/css/ `and `static/image/`, respectively, and templates go into `templates/`. Translations go into `locales/` -A Standard directory structure like this makes it easier to navigate through your code. That said, do note, that this is not actually *required* to make your plugin run. If you want to make use of our i18n system, you need to put your translations into `locales/`, though, in order to have them intergated. (See "Localization" for more info on how to localize your plugin) +A Standard directory structure like this makes it easier to navigate through your code. That said, do note, that this is not actually *required* to make your plugin run. If you want to make use of our i18n system, you need to put your translations into `locales/`, though, in order to have them integrated. (See "Localization" for more info on how to localize your plugin) ## Plugin definition Your plugin definition goes into `ep.json`. In this file you register your hooks, indicate the parts of your plugin and the order of execution. (A documentation of all available events to hook into can be found in chapter [hooks](#all_hooks).) @@ -41,7 +41,7 @@ A hook registration is a pairs of a hook name and a function reference (filename } ``` -Etherpad-lite will expect the part of the hook definition before the colon to be a javascript file and will try to require it. The part after the colon is expected to be a valid function identifier of that module. So, you have to export your hooks, using [`module.exports`](http://nodejs.org/docs/latest/api/modules.html#modules_modules) and register it in `ep.json` as `ep_/path/to/:FUNCTIONNAME`. +Etherpad-lite will expect the part of the hook definition before the colon to be a javascript file and will try to require it. The part after the colon is expected to be a valid function identifier of that module. So, you have to export your hooks, using [`module.exports`](https://nodejs.org/docs/latest/api/modules.html#modules_modules) and register it in `ep.json` as `ep_/path/to/:FUNCTIONNAME`. You can omit the `FUNCTIONNAME` part, if the exported function has got the same name as the hook. So `"authorize" : "ep_flubberworm/foo"` will call the function `exports.authorize` in `ep_flubberworm/foo.js` ### Client hooks and server hooks @@ -89,7 +89,7 @@ Note that it would be far more sane to use `"pre"` in almost any case, but if yo Also, note that dependencies should *also* be listed in your package.json, so they can be `npm install`'d automagically when your plugin gets installed. ## Package definition -Your plugin must also contain a [package definition file](http://npmjs.org/doc/json.html), called package.json, in the project root - this file contains various metadata relevant to your plugin, such as the name and version number, author, project hompage, contributors, a short description, etc. If you publish your plugin on npm, these metadata are used for package search etc., but it's necessary for Etherpad-lite plugins, even if you don't publish your plugin. +Your plugin must also contain a [package definition file](https://docs.npmjs.com/files/package.json), called package.json, in the project root - this file contains various metadata relevant to your plugin, such as the name and version number, author, project hompage, contributors, a short description, etc. If you publish your plugin on npm, these metadata are used for package search etc., but it's necessary for Etherpad-lite plugins, even if you don't publish your plugin. ```json { From 67439545a6c52233c629280eef7b3004d63bbb22 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 21 Sep 2017 09:21:11 +0200 Subject: [PATCH 094/102] Localisation updates from https://translatewiki.net. --- src/locales/diq.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/locales/diq.json b/src/locales/diq.json index b0e1af5f6..c57284ac0 100644 --- a/src/locales/diq.json +++ b/src/locales/diq.json @@ -61,6 +61,7 @@ "pad.modals.connected": "Gırediya.", "pad.modals.reconnecting": "Bloknot da şıma rê fına irtibat kewê no", "pad.modals.forcereconnect": "Mecbur anciya gırê de", + "pad.modals.cancel": "Bıtexelne", "pad.modals.userdup": "Zewbina pençere de bi a", "pad.modals.userdup.explanation": "Ena bloknot ena komputer de yew ra zeder penceran dı akerde asena", "pad.modals.userdup.advice": "Ena pencera ra kar finayışi rê fına irtibat kewê", From 0e1414dccac16892a43e1122ff53d178e210fd0a Mon Sep 17 00:00:00 2001 From: Luiza Pagliari Date: Thu, 21 Sep 2017 17:49:33 -0300 Subject: [PATCH 095/102] Allow 'placeholder' to be a localizable attribute on HTML elements (#3257) --- src/static/js/html10n.js | 87 ++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/src/static/js/html10n.js b/src/static/js/html10n.js index eecbaa0a2..8dea84c28 100644 --- a/src/static/js/html10n.js +++ b/src/static/js/html10n.js @@ -21,7 +21,7 @@ * IN THE SOFTWARE. */ window.html10n = (function(window, document, undefined) { - + // fix console (function() { var noop = function() {}; @@ -80,7 +80,7 @@ window.html10n = (function(window, document, undefined) { return -1; } } - + /** * MicroEvent - to make any js object an event emitter (server or browser) */ @@ -116,7 +116,7 @@ window.html10n = (function(window, document, undefined) { destObject[props[i]] = MicroEvent.prototype[props[i]]; } } - + /** * Loader * The loader is responsible for loading @@ -127,7 +127,7 @@ window.html10n = (function(window, document, undefined) { this.cache = {} // file => contents this.langs = {} // lang => strings } - + Loader.prototype.load = function(lang, cb) { if(this.langs[lang]) return cb() @@ -137,22 +137,22 @@ window.html10n = (function(window, document, undefined) { this.fetch(this.resources[i], lang, function(e) { reqs++; if(e) console.warn(e) - + if (reqs < n) return;// Call back once all reqs are completed cb && cb() }) } } } - + Loader.prototype.fetch = function(href, lang, cb) { var that = this - + if (this.cache[href]) { this.parse(lang, href, this.cache[href], cb) return; } - + var xhr = new XMLHttpRequest() xhr.open('GET', href, /*async: */true) if (xhr.overrideMimeType) { @@ -172,7 +172,7 @@ window.html10n = (function(window, document, undefined) { }; xhr.send(null); } - + Loader.prototype.parse = function(lang, currHref, data, cb) { if ('object' != typeof data) { cb(new Error('A file couldn\'t be parsed as json.')) @@ -192,7 +192,7 @@ window.html10n = (function(window, document, undefined) { } if(lang != l) return cb(new Error(msg)) } - + if ('string' == typeof data[lang]) { // Import rule @@ -200,7 +200,7 @@ window.html10n = (function(window, document, undefined) { var importUrl = data[lang] // relative path - if(data[lang].indexOf("http") != 0 && data[lang].indexOf("/") != 0) { + if(data[lang].indexOf("http") != 0 && data[lang].indexOf("/") != 0) { importUrl = currHref+"/../"+data[lang] } @@ -217,20 +217,20 @@ window.html10n = (function(window, document, undefined) { // TODO: Also store accompanying langs cb() } - - + + /** * The html10n object */ - var html10n = + var html10n = { language : null } MicroEvent.mixin(html10n) - + html10n.macros = {} html10n.rtl = ["ar","dv","fa","ha","he","ks","ku","ps","ur","yi"] - + /** * Get rules for plural forms (shared with JetPack), see: * http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html @@ -668,7 +668,7 @@ window.html10n = (function(window, document, undefined) { return str; }; - + /** * Localize a document * @param langs An array of lang codes defining fallbacks @@ -710,7 +710,7 @@ window.html10n = (function(window, document, undefined) { // translate element itself if necessary this.translateNode(translations, element) } - + function asyncForEach(list, iterator, cb) { var i = 0 , n = list.length @@ -721,7 +721,7 @@ window.html10n = (function(window, document, undefined) { cb() }) } - + function getTranslatableChildren(element) { if(!document.querySelectorAll) { if (!element) return [] @@ -735,29 +735,29 @@ window.html10n = (function(window, document, undefined) { } return element.querySelectorAll('*[data-l10n-id]') } - + html10n.get = function(id, args) { var translations = html10n.translations if(!translations) return console.warn('No translations available (yet)') if(!translations[id]) return console.warn('Could not find string '+id) - + // apply macros var str = translations[id] - + str = substMacros(id, str, args) - + // apply args str = substArguments(str, args) - + return str } - + // replace {{arguments}} with their values or the // associated translation string (based on its key) function substArguments(str, args) { var reArgs = /\{\{\s*([a-zA-Z\.]+)\s*\}\}/ , match - + while (match = reArgs.exec(str)) { if (!match || match.length < 2) return str // argument key not found @@ -775,15 +775,15 @@ window.html10n = (function(window, document, undefined) { str = str.substring(0, match.index) + sub + str.substr(match.index + match[0].length) } - + return str } - + // replace {[macros]} with their values function substMacros(key, str, args) { var regex = /\{\[\s*([a-zA-Z]+)\(([a-zA-Z]+)\)((\s*([a-zA-Z]+)\: ?([ a-zA-Z{}]+),?)+)*\s*\]\}/ //.exec('{[ plural(n) other: are {{n}}, one: is ]}') , match - + while(match = regex.exec(str)) { // a macro has been found // Note: at the moment, only one parameter is supported @@ -791,9 +791,9 @@ window.html10n = (function(window, document, undefined) { , paramName = match[2] , optv = match[3] , opts = {} - + if (!(macroName in html10n.macros)) continue - + if(optv) { optv.match(/(?=\s*)([a-zA-Z]+)\: ?([ a-zA-Z{}]+)(?=,?)/g).forEach(function(arg) { var parts = arg.split(':') @@ -802,7 +802,7 @@ window.html10n = (function(window, document, undefined) { opts[name] = value }) } - + var param if (args && paramName in args) { param = args[paramName] @@ -814,10 +814,10 @@ window.html10n = (function(window, document, undefined) { var macro = html10n.macros[macroName] str = str.substr(0, match.index) + macro(key, param, opts) + str.substr(match.index+match[0].length) } - + return str } - + /** * Applies translations to a DOM node (recursive) */ @@ -840,9 +840,9 @@ window.html10n = (function(window, document, undefined) { console.warn('Couldn\'t parse args for '+str.id) } } - + str.str = html10n.get(str.id, str.args) - + // get attribute name to apply str to var prop , index = str.id.lastIndexOf('.') @@ -852,6 +852,7 @@ window.html10n = (function(window, document, undefined) { , "alt": 1 , "textContent": 1 , "value": 1 + , "placeholder": 1 } if (index > 0 && str.id.substr(index + 1) in attrList) { // an attribute has been specified prop = str.id.substr(index + 1) @@ -883,7 +884,7 @@ window.html10n = (function(window, document, undefined) { } } } - + /** * Builds a translation object from a list of langs (loads the necessary translations) * @param langs Array - a list of langs sorted by priority (default langs should go last) @@ -898,11 +899,11 @@ window.html10n = (function(window, document, undefined) { }, function() { var lang langs.reverse() - + // loop through the priority array... for (var i=0, n=langs.length; i < n; i++) { lang = langs[i] - + if(!lang) continue; if(!(lang in that.loader.langs)) {// uh, we don't have this lang availbable.. // then check for related langs @@ -915,13 +916,13 @@ window.html10n = (function(window, document, undefined) { } if(lang != l) continue; } - + // ... and apply all strings of the current lang in the list // to our build object for (var string in that.loader.langs[lang]) { build[string] = that.loader.langs[lang][string] } - + // the last applied lang will be exposed as the // lang the page was translated to that.language = lang @@ -929,7 +930,7 @@ window.html10n = (function(window, document, undefined) { cb(null, build) }) } - + /** * Returns the language that was last applied to the translations hash * thus overriding most of the formerly applied langs @@ -962,7 +963,7 @@ window.html10n = (function(window, document, undefined) { this.loader = new Loader(resources) this.trigger('indexed') } - + if (document.addEventListener) // modern browsers and IE9+ document.addEventListener('DOMContentLoaded', function() { html10n.index() From bb80085c9acc46b150a1c70e7660254ca26f0e52 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 12 Oct 2017 08:36:19 +0200 Subject: [PATCH 096/102] Localisation updates from https://translatewiki.net. --- src/locales/tr.json | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/locales/tr.json b/src/locales/tr.json index deb3f58c6..0be2588f1 100644 --- a/src/locales/tr.json +++ b/src/locales/tr.json @@ -38,7 +38,7 @@ "pad.wrongPassword": "Parolanız yanlış", "pad.settings.padSettings": "Bloknot Ayarları", "pad.settings.myView": "Görünümüm", - "pad.settings.stickychat": "Ekranda her zaman sohbet edin", + "pad.settings.stickychat": "Sohbeti her zaman ekranda yap", "pad.settings.chatandusers": "Sohbeti ve Kullanıcıları Göster", "pad.settings.colorcheck": "Yazarlık renkleri", "pad.settings.linenocheck": "Satır numaraları", @@ -58,10 +58,12 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Açık Doküman Biçimi)", - "pad.importExport.abiword.innerHTML": "Yalnızca düz metin ya da HTML biçimlerini içe aktarabilirsiniz. Daha fazla gelişmiş içe aktarım özellikleri için AbiWord'ü yükleyin.", + "pad.importExport.abiword.innerHTML": "Yalnızca düz metin ya da HTML biçimlerini içe aktarabilirsiniz. Daha fazla gelişmiş içe aktarım özellikleri için lütfen AbiWord'ü yükleyin.", "pad.modals.connected": "Bağlandı.", "pad.modals.reconnecting": "Bloknotunuza tekrar bağlanılıyor...", "pad.modals.forcereconnect": "Yeniden bağlanmaya zorla", + "pad.modals.reconnecttimer": "Yeniden bağlanmaya çalışılıyor", + "pad.modals.cancel": "İptal", "pad.modals.userdup": "Başka pencerede açıldı", "pad.modals.userdup.explanation": "Bu bloknot bu bilgisayarda birden fazla tarayıcı penceresinde açılmış gibi görünüyor.", "pad.modals.userdup.advice": "Bu pencereden kullanmak için yeniden bağlanın.", @@ -101,7 +103,7 @@ "timeslider.playPause": "Bloknot İçeriğini Oynat / Durdur", "timeslider.backRevision": "Bu bloknottaki bir revizyona geri git", "timeslider.forwardRevision": "Bu bloknatta sonraki revizyona git", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}.{{minutes}}.{{seconds}}", + "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", "timeslider.month.january": "Ocak", "timeslider.month.february": "Şubat", "timeslider.month.march": "Mart", @@ -114,11 +116,11 @@ "timeslider.month.october": "Ekim", "timeslider.month.november": "Kasım", "timeslider.month.december": "Aralık", - "timeslider.unnamedauthors": "{{num}} adsız {[plural(num) one: yazar, other: yazar ]}", + "timeslider.unnamedauthors": "{{num}} isimsiz {[plural(num) one: yazar, other: yazar ]}", "pad.savedrevs.marked": "Bu düzenleme artık kayıtlı bir düzeltme olarak işaretlendi", "pad.savedrevs.timeslider": "Zaman kaydırıcısını ziyaret ederek kaydedilen revizyonları görebilirsiniz", "pad.userlist.entername": "Adınızı girin", - "pad.userlist.unnamed": "Adlandırılmamış", + "pad.userlist.unnamed": "isimsiz", "pad.userlist.guest": "Misafir", "pad.userlist.deny": "Reddet", "pad.userlist.approve": "Onayla", From 8c85205a80b29a39df747bed295b020cda74b950 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 19 Oct 2017 09:01:31 +0200 Subject: [PATCH 097/102] Localisation updates from https://translatewiki.net. --- src/locales/hr.json | 129 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 src/locales/hr.json diff --git a/src/locales/hr.json b/src/locales/hr.json new file mode 100644 index 000000000..36f980dc9 --- /dev/null +++ b/src/locales/hr.json @@ -0,0 +1,129 @@ +{ + "@metadata": { + "authors": [ + "Bugoslav" + ] + }, + "index.newPad": "Novi blokić", + "index.createOpenPad": "ili stvori/otvori blokić s imenom:", + "pad.toolbar.bold.title": "Masno (Ctrl+B)", + "pad.toolbar.italic.title": "Ukošeno (Ctrl+I)", + "pad.toolbar.underline.title": "Podcrtano (Ctrl+U)", + "pad.toolbar.strikethrough.title": "Prekriženo (Ctrl+5)", + "pad.toolbar.ol.title": "Uređeni popis (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Neuređeni popis (Ctrl+Shift+L)", + "pad.toolbar.indent.title": "Uvlaka (TAB)", + "pad.toolbar.unindent.title": "Izvlaka (Shift+TAB)", + "pad.toolbar.undo.title": "Poništi (Ctrl+Z)", + "pad.toolbar.redo.title": "Ponovi (Ctrl+Y)", + "pad.toolbar.clearAuthorship.title": "Ukloni boje autorstva (Ctrl+Shift+C)", + "pad.toolbar.import_export.title": "Uvezi/izvezi iz/na različite datotečne formate", + "pad.toolbar.timeslider.title": "Pokazivač vremenske lente", + "pad.toolbar.savedRevision.title": "Spremi inačicu", + "pad.toolbar.settings.title": "Postavke", + "pad.toolbar.embed.title": "Dijeli i umetni ovaj blokić", + "pad.toolbar.showusers.title": "Pokaži suradnike ovoga blokića", + "pad.colorpicker.save": "Spremi", + "pad.colorpicker.cancel": "Otkaži", + "pad.loading": "Učitavanje...", + "pad.noCookie": "Kolačić nije pronađen. Molimo Vas da uključite kolačiće u Vašem pregledniku!", + "pad.passwordRequired": "Potrebna Vam je zaporka za pristup ovomu blokiću", + "pad.permissionDenied": "Nemate dopuštenje za pristup ovome blokiću", + "pad.wrongPassword": "Vaša zaporka nije valjana", + "pad.settings.padSettings": "Postavke blokića", + "pad.settings.myView": "Vaš prikaz", + "pad.settings.stickychat": "Stavi čavrljanje uvijek na ekranu", + "pad.settings.chatandusers": "Prikaži čavrljanje i suradnike", + "pad.settings.colorcheck": "Boje autorstva", + "pad.settings.linenocheck": "Brojevi redaka", + "pad.settings.rtlcheck": "Želite li prikaz sadržaja s desna na lijevo?", + "pad.settings.fontType": "Vrsta fonta:", + "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.export": "Izvezi trenutačni blokić kao:", + "pad.importExport.exportetherpad": "Etherpad (virtualni blokići)", + "pad.importExport.exporthtml": "HTML (oblikovanje sadržaja)", + "pad.importExport.exportplain": "Obični tekst (bez oblikovanja)", + "pad.importExport.exportword": "Datoteku Microsoftova Worda", + "pad.importExport.exportpdf": "Datoteku Acrobatova PDF formata", + "pad.importExport.exportopen": "Datoteku formata Open Document (ODF)", + "pad.importExport.abiword.innerHTML": "Možete uvoziti datoteke formata za obični tekst (bez oblikovanja) te datoteke u HTML-u. Za naprednije mogućnosti uvoza molimo Vas, instalirajte program AbiWord.", + "pad.modals.connected": "Povezano.", + "pad.modals.reconnecting": "Ponovo Vas povezujemo s Vašim blokićem...", + "pad.modals.forcereconnect": "Prisilno se ponovo poveži", + "pad.modals.reconnecttimer": "Sustav Vas pokušava ponovo povezati", + "pad.modals.cancel": "Odustani", + "pad.modals.userdup": "Otvoreno u drugom prozoru", + "pad.modals.userdup.explanation": "Čini se da je ovaj blokić otvoren u više od jednoga prozora Vašega preglednika na ovom računalu.", + "pad.modals.userdup.advice": "Ponovo se povežite da biste rabili ovaj prozor.", + "pad.modals.unauth": "Niste ovlašteni", + "pad.modals.unauth.explanation": "Vaše su ovlasti promijenjene za vrijeme dok ste pregledavali stranicu.\nPokušajte se ponovo spojiti.", + "pad.modals.looping.explanation": "Postoje komunikacijski problemi sa sinkronizacijskim poslužiteljem.", + "pad.modals.looping.cause": "Možda ste se spojili preko nekompatibilne sigurnosne stijene ili proxyja.", + "pad.modals.initsocketfail": "Poslužitelj nije dostupan.", + "pad.modals.initsocketfail.explanation": "Ne mogu se povezati sa sinkronizacijskim poslužiteljem.", + "pad.modals.initsocketfail.cause": "Najvjerojatnije je došlo do problema s Vašim preglednikom ili s Vašom internetskom vezom.", + "pad.modals.slowcommit.explanation": "Poslužitelj ne šalje odziv.", + "pad.modals.slowcommit.cause": "Najvjerojatnije je došlo do problema s dostupnošću mreže.", + "pad.modals.badChangeset.explanation": "Sinkronizacijski poslužitelj označio je Vaše uređivanje kao nedopušteno.", + "pad.modals.badChangeset.cause": "Moguće je da je došlo do pogrješke konfiguracije poslužitelja ili nekog drugog neočekivanog događaja odnosno postupka. Molimo Vas da kontaktirate s Vašim administratorom usluge, ukoliko držite da je ovo pogrješka. Molimo Vas, pokušajte se ponovo spojiti kako biste nastavili s uređivanjem.", + "pad.modals.corruptPad.explanation": "Blokić kom pokušavate pristupiti je oštećen.", + "pad.modals.corruptPad.cause": "Moguće je došlo do pogrješne konfiguracije poslužitelja ili nekog drugog neočekivanog događaja ili postupka. Molimo Vas, kontaktirajte administratora usluge.", + "pad.modals.deleted": "Pobrisano.", + "pad.modals.deleted.explanation": "Blokić je bio uklonjen.", + "pad.modals.disconnected": "Vaša je veza prekinuta.", + "pad.modals.disconnected.explanation": "Veza s poslužiteljem je izgubljena.", + "pad.modals.disconnected.cause": "Moguće je da poslužitelj nije dostupan. Molimo Vas, obavijestite administratora usluge ukoliko se to nastavi događati.", + "pad.share": "Dijeljenje ovoga blokića.", + "pad.share.readonly": "Samo za čitanje", + "pad.share.link": "Poveznica", + "pad.share.emebdcode": "Umetni poveznicu (URL)", + "pad.chat": "Čavrljanje", + "pad.chat.title": "Otvori čavrljanje uz ovaj blokić.", + "pad.chat.loadmessages": "Učitaj više poruka", + "timeslider.pageTitle": "{{appTitle}} Vremenska lenta", + "timeslider.toolbar.returnbutton": "Vrati se natrag na blokić", + "timeslider.toolbar.authors": "Autori:", + "timeslider.toolbar.authorsList": "Nema autora", + "timeslider.toolbar.exportlink.title": "Izvoz", + "timeslider.exportCurrent": "Izvezi trenutačnu inačicu kao:", + "timeslider.version": "Inačica {{version}}", + "timeslider.saved": "Spremljeno dana {{day}}. {{month}} {{year}}.", + "timeslider.playPause": "Izvrti/pauziraj sadržaj blokića", + "timeslider.backRevision": "Idi jednu inačicu ovog blokića natrag", + "timeslider.forwardRevision": "Idi jednu inačicu ovog blokića naprijed", + "timeslider.dateformat": "{{day}}. {{month}}. {{year}}. {{hours}}:{{minutes}}:{{seconds}}", + "timeslider.month.january": "siječnja", + "timeslider.month.february": "veljače", + "timeslider.month.march": "ožujka", + "timeslider.month.april": "travnja", + "timeslider.month.may": "svibnja", + "timeslider.month.june": "lipnja", + "timeslider.month.july": "srpnja", + "timeslider.month.august": "kolovoza", + "timeslider.month.september": "rujna", + "timeslider.month.october": "listopada", + "timeslider.month.november": "studenoga", + "timeslider.month.december": "prosinca", + "timeslider.unnamedauthors": "{{num}} {[plural(num) one: neimenovani autor, plural(num) two: neimenovana autora, plural(num) other: neimenovanih autora ]}", + "pad.savedrevs.marked": "Ova inačica označena je sada kao spremljena inačica", + "pad.savedrevs.timeslider": "Možete vidjeti spremljene inačice rabeći vremensku lentu (timeslider)", + "pad.userlist.entername": "Unesite Vaše suradničko ime", + "pad.userlist.unnamed": "bez imena", + "pad.userlist.guest": "Gost", + "pad.userlist.deny": "Odbij", + "pad.userlist.approve": "Odobri", + "pad.editbar.clearcolors": "Ukloniti boje autorstva u cijelom blokiću?", + "pad.impexp.importbutton": "Uvezi odmah", + "pad.impexp.importing": "Uvoženje...", + "pad.impexp.confirmimport": "Uvoženje datoteke presnimit će trenutačni sadržaj blokića.\nJeste li sigurni da želite nastaviti?", + "pad.impexp.convertFailed": "Nismo bili u mogućnosti uvesti tu datoteku. Molimo Vas, rabite neki drugi format dokumenta ili ručno preslikajte/zalijepite sadržaj", + "pad.impexp.padHasData": "Nismo bili u mogućnosti uvesti navedenu datoteku, jer je blokić već bio mijenjan, molimo Vas uvezite u novi blokić", + "pad.impexp.uploadFailed": "Postavljanje nije uspjelo. molimo Vas, pokušajte ponovo", + "pad.impexp.importfailed": "Uvoz nije uspio", + "pad.impexp.copypaste": "Molimo preslikajte/zalijepite", + "pad.impexp.exportdisabled": "Izvoz u formatu {{type}} nije omogućen. Molimo Vas, kontaktirajte Vašega administratora sustava za više pojedinosti." +} From 266b4a6a515b4a4f78528d36027fe14ecb7cfc03 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 23 Oct 2017 04:59:18 +0200 Subject: [PATCH 098/102] Localisation updates from https://translatewiki.net. --- src/locales/azb.json | 5 +++++ src/locales/hr.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/locales/azb.json b/src/locales/azb.json index 2e550bc3c..4eeec317d 100644 --- a/src/locales/azb.json +++ b/src/locales/azb.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.advice": "بو پئنجره دن ایستفاده ائتمک اوچون یئنی دن متصیل اول", "pad.modals.unauth": "اوْلماز", @@ -91,6 +93,7 @@ "timeslider.exportCurrent": "موجود نوسخه نی بو عونوانلا ائشیگه چیخارت:", "timeslider.version": "{{version}} ورژنی", "timeslider.saved": "ساخلانیلدی {{day}} {{month}}, {{year}}", + "timeslider.playPause": "پد ایچینده‌کیلری یئنه اوْخوت/دۇردور", "timeslider.month.january": "ژانویه", "timeslider.month.february": "فوریه", "timeslider.month.march": "مارس", @@ -103,11 +106,13 @@ "timeslider.month.october": "اوْکتوبر", "timeslider.month.november": "نوْوامبر", "timeslider.month.december": "دسامبر", + "pad.savedrevs.marked": "بۇ نوسخه ایندی ذخیره اوْلونموش کیمی علامتلندی.", "pad.userlist.entername": "آدینیزی یازین", "pad.userlist.unnamed": "آدسیز", "pad.userlist.guest": "قوْناق", "pad.userlist.deny": "دانماق", "pad.userlist.approve": "اوْنایلا", + "pad.editbar.clearcolors": "بوتون سندلرده یازار بوْیالاری سیلینسین می؟", "pad.impexp.importbutton": "ایندی ایچری گتیر", "pad.impexp.importing": "ایچری گتیریلیر...", "pad.impexp.uploadFailed": "آپلود اولونمادی، یئنه چالیشین", diff --git a/src/locales/hr.json b/src/locales/hr.json index 36f980dc9..2c7190f5b 100644 --- a/src/locales/hr.json +++ b/src/locales/hr.json @@ -47,7 +47,7 @@ "pad.importExport.exportetherpad": "Etherpad (virtualni blokići)", "pad.importExport.exporthtml": "HTML (oblikovanje sadržaja)", "pad.importExport.exportplain": "Obični tekst (bez oblikovanja)", - "pad.importExport.exportword": "Datoteku Microsoftova Worda", + "pad.importExport.exportword": "Datoteku programa Microsoft Word", "pad.importExport.exportpdf": "Datoteku Acrobatova PDF formata", "pad.importExport.exportopen": "Datoteku formata Open Document (ODF)", "pad.importExport.abiword.innerHTML": "Možete uvoziti datoteke formata za obični tekst (bez oblikovanja) te datoteke u HTML-u. Za naprednije mogućnosti uvoza molimo Vas, instalirajte program AbiWord.", From 097c07adecfc029da24b744733208d7ab0140355 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 2 Nov 2017 08:12:10 +0100 Subject: [PATCH 099/102] Localisation updates from https://translatewiki.net. --- src/locales/zh-hant.json | 44 ++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/locales/zh-hant.json b/src/locales/zh-hant.json index 6977666b5..e9cac9d49 100644 --- a/src/locales/zh-hant.json +++ b/src/locales/zh-hant.json @@ -11,8 +11,8 @@ "Kly" ] }, - "index.newPad": "新Pad", - "index.createOpenPad": "或創建/開啟以下名稱的pad:", + "index.newPad": "新記事本", + "index.createOpenPad": "或創建/開啟以下名稱的記事本:", "pad.toolbar.bold.title": "粗體(Ctrl-B)", "pad.toolbar.italic.title": "斜體(Ctrl-I)", "pad.toolbar.underline.title": "底線(Ctrl-U)", @@ -28,16 +28,16 @@ "pad.toolbar.timeslider.title": "時間軸", "pad.toolbar.savedRevision.title": "儲存修訂", "pad.toolbar.settings.title": "設定", - "pad.toolbar.embed.title": "分享和嵌入此pad", - "pad.toolbar.showusers.title": "顯示此 pad 的使用者", + "pad.toolbar.embed.title": "分享和嵌入此記事本", + "pad.toolbar.showusers.title": "顯示此記事本的使用者", "pad.colorpicker.save": "儲存", "pad.colorpicker.cancel": "取消", "pad.loading": "載入中...", "pad.noCookie": "找不到 Cookie。請讓你的瀏覽器允許 Cookie!", - "pad.passwordRequired": "您需要密碼才能訪問這個pad", - "pad.permissionDenied": "你沒有訪問這個pad的權限", + "pad.passwordRequired": "您需要密碼才能訪問這個記事本", + "pad.permissionDenied": "你沒有訪問這個記事本的權限", "pad.wrongPassword": "密碼錯誤", - "pad.settings.padSettings": "Pad設定", + "pad.settings.padSettings": "記事本設定", "pad.settings.myView": "我的視窗", "pad.settings.stickychat": "永遠在屏幕上顯示聊天", "pad.settings.chatandusers": "顯示聊天與使用者", @@ -52,7 +52,7 @@ "pad.importExport.import_export": "匯入/匯出", "pad.importExport.import": "上載任何文字檔或文件", "pad.importExport.importSuccessful": "完成!", - "pad.importExport.export": "匯出當前pad為:", + "pad.importExport.export": "匯出目前的記事本為:", "pad.importExport.exportetherpad": "Etherpad", "pad.importExport.exporthtml": "HTML", "pad.importExport.exportplain": "純文字", @@ -61,12 +61,12 @@ "pad.importExport.exportopen": "ODF(開放文件格式)", "pad.importExport.abiword.innerHTML": "您只可以純文字或html格式檔匯入。安裝abiword取得更多進階的匯入功能。", "pad.modals.connected": "已連線。", - "pad.modals.reconnecting": "重新連接到您的pad...", + "pad.modals.reconnecting": "重新連接到您的記事本...", "pad.modals.forcereconnect": "強制重新連線", "pad.modals.reconnecttimer": "嘗試重新連接在", "pad.modals.cancel": "取消", "pad.modals.userdup": "在另一個視窗中開啟", - "pad.modals.userdup.explanation": "此pad似乎在此電腦上的多個瀏覽器視窗中開啟。", + "pad.modals.userdup.explanation": "此記事本似乎在此電腦上的多個瀏覽器視窗中開啟。", "pad.modals.userdup.advice": "重新連接到此視窗。", "pad.modals.unauth": "未授權", "pad.modals.unauth.explanation": "您的權限在查看此頁時發生更改。請嘗試重新連接。", @@ -79,40 +79,40 @@ "pad.modals.slowcommit.cause": "這可能是因為網路連線問題所造成。", "pad.modals.badChangeset.explanation": "您的一個編輯被同步伺服器類為非法。", "pad.modals.badChangeset.cause": "這可能由於伺服器的配置錯誤或遇到意外問題。若您認為這是錯誤,請聯繫伺服器管理員。如要繼續編輯,請嘗試重新連接。", - "pad.modals.corruptPad.explanation": "您試圖存取的平板已損壞。", + "pad.modals.corruptPad.explanation": "您試圖存取的記事本已損壞。", "pad.modals.corruptPad.cause": "這可能由於伺服器的配置錯誤或遇到意外問題。請聯繫伺服器管理員。", "pad.modals.deleted": "已刪除。", - "pad.modals.deleted.explanation": "此pad已被移除。", + "pad.modals.deleted.explanation": "此記事本已被移除。", "pad.modals.disconnected": "您已中斷連線。", "pad.modals.disconnected.explanation": "伺服器連接曾中斷", "pad.modals.disconnected.cause": "伺服器可能無法使用。若此情況持續發生,請通知伺服器管理員。", - "pad.share": "分享此pad", + "pad.share": "分享此記事本", "pad.share.readonly": "唯讀", "pad.share.link": "連結", "pad.share.emebdcode": "嵌入網址", "pad.chat": "聊天功能", - "pad.chat.title": "打開pad聊天功能", + "pad.chat.title": "打開記事本聊天功能", "pad.chat.loadmessages": "載入更多訊息", "timeslider.pageTitle": "{{appTitle}}時間軸", - "timeslider.toolbar.returnbutton": "返回到pad", + "timeslider.toolbar.returnbutton": "返回到記事本", "timeslider.toolbar.authors": "協作者:", "timeslider.toolbar.authorsList": "無協作者", "timeslider.toolbar.exportlink.title": "匯出", "timeslider.exportCurrent": "匯出當前版本為:", "timeslider.version": "版本{{version}}", "timeslider.saved": "{{year}}年{{month}}{{day}}日儲存", - "timeslider.playPause": "放送 / 暫停Pad內容", - "timeslider.backRevision": "返回此Pad的前一次修訂", - "timeslider.forwardRevision": "前往此Pad的前一次修訂", + "timeslider.playPause": "放送 / 暫停記事本內容", + "timeslider.backRevision": "返回此記事本的前一次修訂", + "timeslider.forwardRevision": "前往此記事本的前一次修訂", "timeslider.dateformat": "{{year}}年{{month}}月{{day}}日 {{hours}}:{{minutes}}:{{seconds}}", "timeslider.month.january": "1月", - "timeslider.month.february": "二月", + "timeslider.month.february": "2月", "timeslider.month.march": "3月", "timeslider.month.april": "4月", "timeslider.month.may": "5月", "timeslider.month.june": "6月", "timeslider.month.july": "7月", - "timeslider.month.august": "八月", + "timeslider.month.august": "8月", "timeslider.month.september": "9月", "timeslider.month.october": "10月", "timeslider.month.november": "11月", @@ -128,9 +128,9 @@ "pad.editbar.clearcolors": "清除整個文檔的協作者顏色區別嗎?", "pad.impexp.importbutton": "現在匯入", "pad.impexp.importing": "匯入中...", - "pad.impexp.confirmimport": "匯入的檔案將會覆蓋pad內目前的文字。您確定要繼續嗎?", + "pad.impexp.confirmimport": "匯入的檔案將會覆蓋記事本內目前的文字。您確定要繼續嗎?", "pad.impexp.convertFailed": "未能匯入此檔案。請以其他檔案格式或手動複製貼上匯入。", - "pad.impexp.padHasData": "此Pad已異動過所以無法匯入該檔案,請匯入至另一個Pad試試。", + "pad.impexp.padHasData": "此記事本已異動過所以無法匯入該檔案,請匯入至另一個記事本試試。", "pad.impexp.uploadFailed": "上載失敗,請重試", "pad.impexp.importfailed": "匯入失敗", "pad.impexp.copypaste": "請複製貼上", From e347f12c71f6b85fa944a2e068344fe6f2713f8a Mon Sep 17 00:00:00 2001 From: "Stefan (Gared)" Date: Sat, 4 Nov 2017 17:02:25 +0100 Subject: [PATCH 100/102] Updated node version for windows to 8.9.0 --- bin/buildForWindows.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/buildForWindows.sh b/bin/buildForWindows.sh index fddb96a1f..a9fbd70b1 100755 --- a/bin/buildForWindows.sh +++ b/bin/buildForWindows.sh @@ -1,6 +1,6 @@ #!/bin/sh -NODE_VERSION="6.9.2" +NODE_VERSION="8.9.0" #Move to the folder where ep-lite is installed cd `dirname $0` From e7b72f2234bbcf43f108fb5f8545e4c58e707fb6 Mon Sep 17 00:00:00 2001 From: "Stefan (Gared)" Date: Sat, 4 Nov 2017 17:17:58 +0100 Subject: [PATCH 101/102] Fix #3111 updating request to 2.83.0 --- src/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package.json b/src/package.json index 3bb76947e..2d62f0645 100644 --- a/src/package.json +++ b/src/package.json @@ -13,7 +13,7 @@ ], "dependencies" : { "etherpad-yajsml" : "0.0.2", - "request" : "2.55.0", + "request" : "2.83.0", "etherpad-require-kernel" : "1.0.9", "resolve" : "1.1.7", "socket.io" : "1.7.3", From baa372763ce8fa8cf5a7645d5d46784afa22ab2c Mon Sep 17 00:00:00 2001 From: "Stefan (Gared)" Date: Sat, 4 Nov 2017 17:24:29 +0100 Subject: [PATCH 102/102] Release version 1.6.2 --- src/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package.json b/src/package.json index 2d62f0645..a182fd973 100644 --- a/src/package.json +++ b/src/package.json @@ -55,6 +55,6 @@ "repository" : { "type" : "git", "url" : "http://github.com/ether/etherpad-lite.git" }, - "version" : "1.6.1", + "version" : "1.6.2", "license" : "Apache-2.0" }