This commit is contained in:
John McLear 2014-11-15 15:39:46 +00:00
commit 4986dd11ee
36 changed files with 626 additions and 199 deletions

View File

@ -74,6 +74,10 @@ You can initially modify the settings in `settings.json`. (If you need to handle
You should use a dedicated database such as "mysql", if you are planning on using etherpad-in a production environment, since the "dirtyDB" database driver is only for testing and/or development purposes.
## Plugins and themes
Etherpad is very customizable through plugins. Instructions for installing themes and plugins can be found in [the plugin wiki article](https://github.com/ether/etherpad-lite/wiki/Available-Plugins).
## Helpful resources
The [wiki](https://github.com/ether/etherpad-lite/wiki) is your one-stop resource for Tutorials and How-to's, really check it out! Also, feel free to improve these wiki pages.

122
src/locales/bcc.json Normal file
View File

@ -0,0 +1,122 @@
{
"@metadata": {
"authors": [
"Baloch Afghanistan"
]
},
"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": "خط خورده",
"pad.toolbar.ol.title": "فهرست مرتب شده",
"pad.toolbar.ul.title": "فهرست مرتب نشده",
"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.clearAuthorship.title": "پاک‌کردن رنگ‌های نویسندگی",
"pad.toolbar.import_export.title": "درون‌ریزی/برون‌ریزی از/به قالب‌های مختلف",
"pad.toolbar.timeslider.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.passwordRequired": "برای دسترسی به این دفترچه یادداشت نیاز به یک گذرواژه دارید",
"pad.permissionDenied": "شرمنده، شما را اجازت په دسترسی ای صفحه نیست.",
"pad.wrongPassword": "گذرواژه‌ی شما درست نیست",
"pad.settings.padSettings": "تنظیمات دفترچه یادداشت",
"pad.settings.myView": "نمای من",
"pad.settings.stickychat": "گفتگو همیشه روی صفحه نمایش باشد",
"pad.settings.colorcheck": "رنگ‌های نویسندگی",
"pad.settings.linenocheck": "شماره‌ی خطوط",
"pad.settings.rtlcheck": "خواندن محتوا از راست به چپ؟",
"pad.settings.fontType": "نوع قلم:",
"pad.settings.fontType.normal": "نرمال",
"pad.settings.fontType.monospaced": "Monospace",
"pad.settings.globalView": "نمای سراسری",
"pad.settings.language": "زبان:",
"pad.importExport.import_export": "درون‌ریزی/برون‌ریزی",
"pad.importExport.import": "بارگذاری پرونده‌ی متنی یا سند",
"pad.importExport.importSuccessful": "موفقیت آمیز بود!",
"pad.importExport.export": "برون‌ریزی این دفترچه یادداشت با قالب:",
"pad.importExport.exporthtml": "HTML",
"pad.importExport.exportplain": "سادگین متن",
"pad.importExport.exportword": "Microsoft Word",
"pad.importExport.exportpdf": "PDF",
"pad.importExport.exportopen": "ODF (قالب سند باز)",
"pad.importExport.exportdokuwiki": "DokuWiki",
"pad.importExport.abiword.innerHTML": "شما تنها می‌توانید از قالب متن ساده یا اچ‌تی‌ام‌ال درون‌ریزی کنید. برای بیشتر شدن ویژگی‌های درون‌ریزی پیشرفته <a href=\"https://github.com/ether/etherpad-lite/wiki/How-to-enable-importing-and-exporting-different-file-formats-in-Ubuntu-or-OpenSuse-or-SLES-with-AbiWord\">AbiWord</a> را نصب کنید.",
"pad.modals.connected": "متصل شد.",
"pad.modals.reconnecting": "در حال اتصال دوباره به دفترچه یادداشت شما..",
"pad.modals.forcereconnect": "واداشتن به اتصال دوباره",
"pad.modals.userdup": "در پنجره‌ای دیگر باز شد",
"pad.modals.userdup.explanation": "گمان می‌رود این دفترچه یادداشت در بیش از یک پنجره‌ی مرورگر باز شده‌است.",
"pad.modals.userdup.advice": "برای استفاده از این پنجره دوباره وصل شوید.",
"pad.modals.unauth": "مجاز نیست",
"pad.modals.unauth.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.badChangeset.explanation": "ویرایشی که شما انجام داده‌اید توسط سرور همگام‌سازی نادرست طیقه‌بندی شده‌است.",
"pad.modals.badChangeset.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": "پیوند",
"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.exportCurrent": "برون‌ریزی نگارش کنونی به عنوان:",
"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": "دسمبر",
"timeslider.unnamedauthors": "{{num}} نویسندهٔ بی‌نام",
"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.confirmimport": "با درون‌ریزی یک پرونده نوشتهٔ کنونی دفترچه پاک می‌شود. آیا می‌خواهید ادامه دهید؟",
"pad.impexp.convertFailed": "ما نمی‌توانیم این پرونده را درون‌ریزی کنیم. خواهشمندیم قالب دیگری برای سندتان انتخاب کرده یا بصورت دستی آنرا کپی کنید",
"pad.impexp.uploadFailed": "آپلود انجام نشد، دوباره تلاش کنید",
"pad.impexp.importfailed": "درون‌ریزی انجام نشد",
"pad.impexp.copypaste": "کپی پیست کنید",
"pad.impexp.exportdisabled": "برون‌ریزی با قالب {{type}} از کار افتاده است. برای جزئیات بیشتر با مدیر سیستمتان تماس بگیرید."
}

View File

@ -12,9 +12,9 @@
"pad.toolbar.bold.title": "Fett (Strg-B)",
"pad.toolbar.italic.title": "Kursiv (Strg-I)",
"pad.toolbar.underline.title": "Unterstrichen (Strg-U)",
"pad.toolbar.strikethrough.title": "Durchgestrichen",
"pad.toolbar.ol.title": "Nummerierte Liste",
"pad.toolbar.ul.title": "Ungeordnete Liste",
"pad.toolbar.strikethrough.title": "Durchgestrichen (Strg+5)",
"pad.toolbar.ol.title": "Nummerierte Liste (Strg+Shift+N)",
"pad.toolbar.ul.title": "Ungeordnete Liste (Strg+Shift+L)",
"pad.toolbar.indent.title": "Einrücken (TAB)",
"pad.toolbar.unindent.title": "Ausrücken (Shift+TAB)",
"pad.toolbar.undo.title": "Rückgängig (Strg-Z)",

View File

@ -2,17 +2,17 @@
"index.newPad": "New Pad",
"index.createOpenPad": "or create/open a Pad with the name:",
"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": "Strikethrough (Ctrl-5)",
"pad.toolbar.ol.title": "Ordered list (Ctrl-Shift-N)",
"pad.toolbar.ul.title": "Unordered List (Ctrl-Shift-L)",
"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": "Strikethrough (Ctrl+5)",
"pad.toolbar.ol.title": "Ordered list (Ctrl+Shift+N)",
"pad.toolbar.ul.title": "Unordered List (Ctrl+Shift+L)",
"pad.toolbar.indent.title": "Indent (TAB)",
"pad.toolbar.unindent.title": "Outdent (Shift+TAB)",
"pad.toolbar.undo.title": "Undo (Ctrl-Z)",
"pad.toolbar.redo.title": "Redo (Ctrl-Y)",
"pad.toolbar.clearAuthorship.title": "Clear Authorship Colors",
"pad.toolbar.undo.title": "Undo (Ctrl+Z)",
"pad.toolbar.redo.title": "Redo (Ctrl+Y)",
"pad.toolbar.clearAuthorship.title": "Clear Authorship Colors (Ctrl+Shift+C)",
"pad.toolbar.import_export.title": "Import/Export from/to different file formats",
"pad.toolbar.timeslider.title": "Timeslider",
"pad.toolbar.savedRevision.title": "Save Revision",

View File

@ -18,9 +18,9 @@
"pad.toolbar.bold.title": "Negrita (Ctrl-B)",
"pad.toolbar.italic.title": "Cursiva (Ctrl-I)",
"pad.toolbar.underline.title": "Subrayado (Ctrl-U)",
"pad.toolbar.strikethrough.title": "Tachado",
"pad.toolbar.ol.title": "Lista ordenada",
"pad.toolbar.ul.title": "Lista desordenada",
"pad.toolbar.strikethrough.title": "Tachado (Ctrl+5)",
"pad.toolbar.ol.title": "Lista ordenada (Ctrl+Mayús+N)",
"pad.toolbar.ul.title": "Lista desordenada (Ctrl+Mayús+L)",
"pad.toolbar.indent.title": "Sangría (TAB)",
"pad.toolbar.unindent.title": "Eliminar sangría (Shift+TAB)",
"pad.toolbar.undo.title": "Deshacer (Ctrl-Z)",

View File

@ -16,7 +16,8 @@
"Rastus Vernon",
"Stephane Cottin",
"Tux-tn",
"Maxim21"
"Maxim21",
"Boniface"
]
},
"index.newPad": "Nouveau pad",
@ -24,9 +25,9 @@
"pad.toolbar.bold.title": "Gras (Ctrl-B)",
"pad.toolbar.italic.title": "Italique (Ctrl-I)",
"pad.toolbar.underline.title": "Souligné (Ctrl-U)",
"pad.toolbar.strikethrough.title": "Barré",
"pad.toolbar.ol.title": "Liste ordonnée",
"pad.toolbar.ul.title": "Liste non ordonnée",
"pad.toolbar.strikethrough.title": "Barré (Ctrl+5)",
"pad.toolbar.ol.title": "Liste ordonnée (Ctrl+Shift+N)",
"pad.toolbar.ul.title": "Liste non ordonnée (Ctrl+Shift+L)",
"pad.toolbar.indent.title": "Indenter (TAB)",
"pad.toolbar.unindent.title": "Désindenter (Maj+TAB)",
"pad.toolbar.undo.title": "Annuler (Ctrl-Z)",
@ -49,7 +50,7 @@
"pad.settings.stickychat": "Toujours afficher le chat",
"pad.settings.colorcheck": "Couleurs didentification",
"pad.settings.linenocheck": "Numéros de lignes",
"pad.settings.rtlcheck": "Lecture de droite à gauche",
"pad.settings.rtlcheck": "Le contenu doit-il être lu de droite à gauche ?",
"pad.settings.fontType": "Police :",
"pad.settings.fontType.normal": "Normal",
"pad.settings.fontType.monospaced": "Monospace",
@ -57,7 +58,7 @@
"pad.settings.language": "Langue :",
"pad.importExport.import_export": "Importer/Exporter",
"pad.importExport.import": "Charger un texte ou un document",
"pad.importExport.importSuccessful": "Réussi!",
"pad.importExport.importSuccessful": "Réussi !",
"pad.importExport.export": "Exporter le pad actuel comme :",
"pad.importExport.exporthtml": "HTML",
"pad.importExport.exportplain": "Texte brut",
@ -83,7 +84,7 @@
"pad.modals.slowcommit.cause": "Ce problème peut venir d'une mauvaise connectivité au réseau.",
"pad.modals.badChangeset.explanation": "Une modification que vous avez effectuée a été classée comme illégale par le serveur de synchronisation.",
"pad.modals.badChangeset.cause": "Cela peut être dû à une mauvaise configuration du serveur ou à un autre comportement inattendu. Veuillez contacter ladministrateur du service, si vous pensez que cest une erreur. Essayez de vous reconnecter pour continuer à modifier.",
"pad.modals.corruptPad.explanation": "Le bloc auquel vous essayez daccéder est corrompu.",
"pad.modals.corruptPad.explanation": "Le pad auquel vous essayez daccéder est corrompu.",
"pad.modals.corruptPad.cause": "Cela peut être dû à une mauvaise configuration du serveur ou à un autre comportement inattendu. Veuillez contacter ladministrateur du service.",
"pad.modals.deleted": "Supprimé.",
"pad.modals.deleted.explanation": "Ce pad a été supprimé.",
@ -102,22 +103,22 @@
"timeslider.toolbar.authors": "Auteurs :",
"timeslider.toolbar.authorsList": "Aucun auteur",
"timeslider.toolbar.exportlink.title": "Exporter",
"timeslider.exportCurrent": "Exporter la version actuelle en :",
"timeslider.exportCurrent": "Exporter la version actuelle sous :",
"timeslider.version": "Version {{version}}",
"timeslider.saved": "Enregistré le {{day}} {{month}} {{year}}",
"timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}",
"timeslider.month.january": "Janvier",
"timeslider.month.february": "Février",
"timeslider.month.march": "Mars",
"timeslider.month.april": "Avril",
"timeslider.month.may": "Mai",
"timeslider.month.june": "Juin",
"timeslider.month.july": "Juillet",
"timeslider.month.august": "Août",
"timeslider.month.september": "Septembre",
"timeslider.month.october": "Octobre",
"timeslider.month.november": "Novembre",
"timeslider.month.december": "Décembre",
"timeslider.month.january": "janvier",
"timeslider.month.february": "février",
"timeslider.month.march": "mars",
"timeslider.month.april": "avril",
"timeslider.month.may": "mai",
"timeslider.month.june": "juin",
"timeslider.month.july": "juillet",
"timeslider.month.august": "août",
"timeslider.month.september": "septembre",
"timeslider.month.october": "octobre",
"timeslider.month.november": "novembre",
"timeslider.month.december": "décembre",
"timeslider.unnamedauthors": "{{num}} {[plural(num) one: auteur anonyme, other: auteurs anonymes ]}",
"pad.savedrevs.marked": "Cette révision est maintenant marquée comme révision enregistrée",
"pad.userlist.entername": "Entrez votre nom",
@ -128,10 +129,10 @@
"pad.editbar.clearcolors": "Effacer les couleurs de paternité dans tout le document ?",
"pad.impexp.importbutton": "Importer maintenant",
"pad.impexp.importing": "Import en cours...",
"pad.impexp.confirmimport": "Importer un fichier écrasera le texte actuel du pad. Êtes-vous sûr de vouloir le faire?",
"pad.impexp.confirmimport": "Importer un fichier écrasera le texte actuel du pad. Êtes-vous sûr de vouloir le faire ?",
"pad.impexp.convertFailed": "Nous ne pouvons pas importer ce fichier. Veuillez utiliser un autre format de document ou faire un copier/coller manuel",
"pad.impexp.uploadFailed": "Le téléchargement a échoué, veuillez réessayer",
"pad.impexp.importfailed": "Échec de l'importation",
"pad.impexp.copypaste": "Veuillez copier/coller",
"pad.impexp.exportdisabled": "Exporter au format {{type}} est désactivé. Veuillez contacter votre administrateur système pour plus de détails."
"pad.impexp.exportdisabled": "L'option d'export au format {{type}} est désactivée. Veuillez contacter votre administrateur système pour plus de détails."
}

View File

@ -12,9 +12,9 @@
"pad.toolbar.bold.title": "בולט (Ctrl-B)",
"pad.toolbar.italic.title": "נטוי (Ctrl-I)",
"pad.toolbar.underline.title": "קו תחתי (Ctrl-U)",
"pad.toolbar.strikethrough.title": "קו מוחק",
"pad.toolbar.ol.title": "רשימה ממוספרת",
"pad.toolbar.ul.title": "רשימה",
"pad.toolbar.strikethrough.title": "קו מוחק (Ctrl+5)",
"pad.toolbar.ol.title": "רשימה ממוספרת (Ctrl+Shift+N)",
"pad.toolbar.ul.title": "רשימת תבליטים (Ctrl+Shift+L)",
"pad.toolbar.indent.title": "הזחה (טאב)",
"pad.toolbar.unindent.title": "צמצום הזחה (שיפט–טאב)",
"pad.toolbar.undo.title": "ביטול (Ctrl-Z)",

View File

@ -4,7 +4,8 @@
"Beta16",
"Gianfranco",
"Muxator",
"Vituzzu"
"Vituzzu",
"Macofe"
]
},
"index.newPad": "Nuovo Pad",
@ -12,9 +13,9 @@
"pad.toolbar.bold.title": "Grassetto (Ctrl-B)",
"pad.toolbar.italic.title": "Corsivo (Ctrl-I)",
"pad.toolbar.underline.title": "Sottolineato (Ctrl-U)",
"pad.toolbar.strikethrough.title": "Barrato",
"pad.toolbar.ol.title": "Elenco numerato",
"pad.toolbar.ul.title": "Elenco puntato",
"pad.toolbar.strikethrough.title": "Barrato (Ctrl+5)",
"pad.toolbar.ol.title": "Elenco numerato (Ctrl+Shift+N)",
"pad.toolbar.ul.title": "Elenco puntato (Ctrl+Shift+L)",
"pad.toolbar.indent.title": "Rientro (TAB)",
"pad.toolbar.unindent.title": "Riduci rientro (Shift+TAB)",
"pad.toolbar.undo.title": "Annulla (Ctrl-Z)",

View File

@ -6,16 +6,16 @@
},
"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": "取り消し線",
"pad.toolbar.ol.title": "番号付きリスト",
"pad.toolbar.ul.title": "番号なしリスト",
"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.undo.title": "元に戻す (Ctrl+Z)",
"pad.toolbar.redo.title": "やり直し (Ctrl+Y)",
"pad.toolbar.clearAuthorship.title": "作者の色分けを消去",
"pad.toolbar.import_export.title": "他の形式のファイルのインポート/エクスポート",
"pad.toolbar.timeslider.title": "タイムスライダー",

View File

@ -6,8 +6,8 @@
]
},
"index.newPad": "Neie Pad",
"pad.toolbar.ol.title": "Numeréiert Lëscht",
"pad.toolbar.ul.title": "Net-numeréiert Lëscht",
"pad.toolbar.ol.title": "Numeréiert Lëscht (Ctrl+Shift+N)",
"pad.toolbar.ul.title": "Net-numeréiert Lëscht (Ctrl+Shift+L)",
"pad.toolbar.undo.title": "Réckgängeg (Ctrl-Z)",
"pad.toolbar.redo.title": "Widderhuelen (Ctrl-Y)",
"pad.toolbar.savedRevision.title": "Versioun späicheren",

75
src/locales/lki.json Normal file
View File

@ -0,0 +1,75 @@
{
"@metadata": {
"authors": [
"Hosseinblue"
]
},
"index.newPad": ازۀpad",
"index.createOpenPad": ":ئۀ وسیلۀ نؤمpadسازین/وآز کردن یه گلۀ",
"pad.toolbar.bold.title": "پررنگ-تئژ(Ctrl-B)",
"pad.toolbar.italic.title": "ایتالیک (Ctrl-I)",
"pad.toolbar.underline.title": "ژئر خطی(Ctrl-U)",
"pad.toolbar.strikethrough.title": "خط هوواردئ",
"pad.toolbar.ol.title": "فئرست رزگی-مرتب",
"pad.toolbar.ul.title": "نۀچنریا-نامرتب",
"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.clearAuthorship.title": "پاکاکردن رنگۀل تالیفی",
"pad.toolbar.import_export.title": "دربردن/ئه نؤم ئآووردن ئۀ/ئِِژ فرمتۀل گوناگون",
"pad.toolbar.timeslider.title": "اسلایدر وختی-زمانی",
"pad.toolbar.savedRevision.title": "ذخیرل دسکاریۀل",
"pad.toolbar.settings.title": "تنظیمۀل",
"pad.toolbar.embed.title": "بۀشاکردن ؤ نیائن(اشتراک ونشاندن)ئۀ نؤم سایت",
"pad.toolbar.showusers.title": "نیشان دائن کاربر ئۀ نؤم ئئ\npad",
"pad.colorpicker.save": "ذخیرۀ",
"pad.colorpicker.cancel": "ئآهووسانن-لغو",
"pad.loading": "...(loading)بارنیائن",
"pad.passwordRequired": "هؤمۀ رمزتؤنه گرۀکۀ-لازمۀ ئۀرا اتصال ئئ \npad",
"pad.wrongPassword": "رمزۀ تؤن دؤرس نیۀ",
"pad.settings.padSettings": "pad تنظیمۀل",
"pad.settings.myView": "نمایش-سئرکردن مه",
"pad.settings.stickychat": "چت همؤیشۀ ئۀ ولگۀ نمایش بوو",
"pad.settings.colorcheck": "رنگۀل تالیفی",
"pad.settings.linenocheck": "شؤمارۀل خطی",
"pad.settings.fontType": ":شئؤۀ فؤنت",
"pad.settings.fontType.normal": "عادی",
"pad.settings.fontType.monospaced": "پئنی-پهنا",
"pad.settings.globalView": "نمایش جئ هانی",
"pad.settings.language": ":زوون",
"pad.importExport.import_export": "در بردن/ئه نؤم ئآووردن",
"pad.importExport.import": "بارنیائن هر جور نوشته یا سندئ",
"pad.importExport.importSuccessful": "! موفق بی-پیرووز بی",
"pad.importExport.exporthtml": "html",
"pad.importExport.exportplain": "متن پئن-درئژ",
"pad.importExport.exportword": "مایکروسافت وورد",
"pad.importExport.exportpdf": "پی دی اف",
"pad.modals.connected": "وصل بیۀ",
"pad.modals.deleted": "پاک بیا-حذف بی",
"pad.share.readonly": "تنیا بخؤۀن",
"pad.share.link": "لینک",
"pad.chat": "گپ",
"pad.chat.loadmessages": "پئامۀلئ تر باره سۀر",
"timeslider.toolbar.exportlink.title": "در بِردن",
"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.importfailed": "وارد نؤنئ-خطای واردکردن"
}

View File

@ -10,9 +10,9 @@
"pad.toolbar.bold.title": "Задебелено (Ctrl-B)",
"pad.toolbar.italic.title": "Косо (Ctrl-I)",
"pad.toolbar.underline.title": "Подвлечено (Ctrl-U)",
"pad.toolbar.strikethrough.title": "Прецртано",
"pad.toolbar.ol.title": "Подреден список",
"pad.toolbar.ul.title": "Неподреден список",
"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)",

View File

@ -5,7 +5,8 @@
"Luckas",
"Tuliouel",
"Waldir",
"Imperadeiro98"
"Imperadeiro98",
"Macofe"
]
},
"index.newPad": "Nova Nota",
@ -13,9 +14,9 @@
"pad.toolbar.bold.title": "Negrito (Ctrl-B)",
"pad.toolbar.italic.title": "Itálico (Ctrl-I)",
"pad.toolbar.underline.title": "Sublinhado (Ctrl-U)",
"pad.toolbar.strikethrough.title": "Riscar",
"pad.toolbar.ol.title": "Lista ordenada",
"pad.toolbar.ul.title": "Lista desordenada",
"pad.toolbar.strikethrough.title": "Riscar (Ctrl+5)",
"pad.toolbar.ol.title": "Lista ordenada (Ctrl+Shift+N)",
"pad.toolbar.ul.title": "Lista desordenada (Ctrl+Shift+L)",
"pad.toolbar.indent.title": "Avançar (TAB)",
"pad.toolbar.unindent.title": "Recuar (Shift+TAB)",
"pad.toolbar.undo.title": "Desfazer (Ctrl-Z)",
@ -71,6 +72,7 @@
"pad.modals.disconnected.cause": "O servidor pode estar indisponível. Por favor, notifique o administrador de serviço se isto continuar a acontecer.",
"pad.share": "Compartilhar este pad",
"pad.share.readonly": "Somente para leitura",
"pad.share.link": "Ligação",
"pad.chat": "Bate-papo",
"pad.chat.title": "Abrir o bate-papo para este pad.",
"pad.chat.loadmessages": "Carregar mais mensagens",

View File

@ -11,9 +11,9 @@
"pad.toolbar.bold.title": "Fet (Ctrl-B)",
"pad.toolbar.italic.title": "Kursiv (Ctrl-I)",
"pad.toolbar.underline.title": "Understruken (Ctrl-U)",
"pad.toolbar.strikethrough.title": "Genomstruken",
"pad.toolbar.ol.title": "Numrerad lista",
"pad.toolbar.ul.title": "Osorterad lista",
"pad.toolbar.strikethrough.title": "Genomstruken (Ctrl+5)",
"pad.toolbar.ol.title": "Numrerad lista (Ctrl+Shift+N)",
"pad.toolbar.ul.title": "Onumrerad lista (Ctrl+Shift+L)",
"pad.toolbar.indent.title": "Öka indrag (TABB)",
"pad.toolbar.unindent.title": "Minska indrag (Shift+TABB)",
"pad.toolbar.undo.title": "Ångra (Ctrl-Z)",
@ -52,7 +52,7 @@
"pad.importExport.exportpdf": "PDF",
"pad.importExport.exportopen": "ODF (Open Document Format)",
"pad.importExport.exportdokuwiki": "DokuWiki",
"pad.importExport.abiword.innerHTML": "Du kan endast importera från oformaterad text eller html-format. För mer avancerade importeringsfunktioner, var god <a href=\"https://github.com/ether/etherpad-lite/wiki/How-to-enable-importing-and-exporting-different-file-formats-in-Ubuntu-or-OpenSuse-or-SLES-with-AbiWord\">installera abiword</a>.",
"pad.importExport.abiword.innerHTML": "Du kan endast importera från oformaterad text eller HTML-format. För mer avancerade importeringsfunktioner, var god <a href=\"https://github.com/ether/etherpad-lite/wiki/How-to-enable-importing-and-exporting-different-file-formats-in-Ubuntu-or-OpenSuse-or-SLES-with-AbiWord\">installera abiword</a>.",
"pad.modals.connected": "Ansluten.",
"pad.modals.reconnecting": "Återansluter till ditt block...",
"pad.modals.forcereconnect": "Tvinga återanslutning",
@ -60,7 +60,7 @@
"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.",
"pad.modals.unauth": "Inte godkänd",
"pad.modals.unauth.explanation": "Din behörighet ändrades medan du visar denna sida. Försök att återansluta.",
"pad.modals.unauth.explanation": "Din behörighet ändrades medan du visade denna sida. Försök att återansluta.",
"pad.modals.looping.explanation": "Kommunikationsproblem med synkroniseringsservern har uppstått.",
"pad.modals.looping.cause": "Kanske du är ansluten via en inkompatibel brandvägg eller proxy.",
"pad.modals.initsocketfail": "Servern kan inte nås.",
@ -69,7 +69,7 @@
"pad.modals.slowcommit.explanation": "Servern svarar inte.",
"pad.modals.slowcommit.cause": "Detta kan bero på problem med nätverksanslutningen.",
"pad.modals.badChangeset.explanation": "En redigering som du gjort klassificerades som otillåten av synkroniseringsservern.",
"pad.modals.badChangeset.cause": "Detta kan bero på en felaktig konfiguration av servern eller något annat oväntad beteende. Var god kontakta tjänstadministratören om du anser att detta är ett fel. Försök ansluta igen för att fortsätta redigera.",
"pad.modals.badChangeset.cause": "Detta kan bero på en felaktig konfiguration av servern eller något annat oväntad beteende. Var god kontakta tjänsteadministratören om du upplever att detta är ett fel. Försök att ansluta igen för att fortsätta redigera.",
"pad.modals.corruptPad.explanation": "Blocket du försöker komma åt är skadat.",
"pad.modals.corruptPad.cause": "Detta kan bero på en felaktig konfiguration av servern eller något annat oväntad beteende. Var god kontakta tjänstadministratören.",
"pad.modals.deleted": "Raderad.",
@ -84,7 +84,7 @@
"pad.chat": "Chatt",
"pad.chat.title": "Öppna chatten för detta block.",
"pad.chat.loadmessages": "Läs in fler meddelanden",
"timeslider.pageTitle": "Tidsreglage för {{appTitle}}",
"timeslider.pageTitle": "{{appTitle}} tidsreglage",
"timeslider.toolbar.returnbutton": "Återvänd till blocket",
"timeslider.toolbar.authors": "Författare:",
"timeslider.toolbar.authorsList": "Inga författare",

View File

@ -4,7 +4,8 @@
"Emperyan",
"Erdemaslancan",
"Joseph",
"Meelo"
"Meelo",
"Trockya"
]
},
"index.newPad": "Yeni Bloknot",
@ -12,13 +13,13 @@
"pad.toolbar.bold.title": "Kalın (Ctrl-B)",
"pad.toolbar.italic.title": "Eğik (Ctrl-I)",
"pad.toolbar.underline.title": "Altı Çizili (Ctrl-U)",
"pad.toolbar.strikethrough.title": "Üstü Çizili",
"pad.toolbar.ol.title": "Sıralı liste",
"pad.toolbar.ul.title": "Sırasız Liste",
"pad.toolbar.strikethrough.title": "Üstü Çizili (Ctrl+5)",
"pad.toolbar.ol.title": "Sıralı liste (Ctrl+Shift+N)",
"pad.toolbar.ul.title": "Sırasız Liste (Ctrl+Shift+L)",
"pad.toolbar.indent.title": "Girintiyi arttır (TAB)",
"pad.toolbar.unindent.title": "Girintiyi azalt (Shift+TAB)",
"pad.toolbar.undo.title": "Geri Al (Ctrl-Z)",
"pad.toolbar.redo.title": "Yenile (Ctrl-Y)",
"pad.toolbar.redo.title": "Yinele (Ctrl+Y)",
"pad.toolbar.clearAuthorship.title": "Yazarlık Renklerini Temizle",
"pad.toolbar.import_export.title": "Farklı dosya biçimlerini içeri/dışarı aktar",
"pad.toolbar.timeslider.title": "Zaman Çizelgesi",

View File

@ -3,7 +3,8 @@
"authors": [
"Baonguyen21022003",
"Minh Nguyen",
"Tuankiet65"
"Tuankiet65",
"Max20091"
]
},
"index.newPad": "Tạo một Pad mới",
@ -11,9 +12,9 @@
"pad.toolbar.bold.title": "In đậm (Ctrl-B)",
"pad.toolbar.italic.title": "In nghiêng (Ctrl-I)",
"pad.toolbar.underline.title": "Gạch chân (Ctrl-U)",
"pad.toolbar.strikethrough.title": "Gạch ngang",
"pad.toolbar.ol.title": "Danh sách Có Đánh số",
"pad.toolbar.ul.title": "Danh sách Không Đánh số",
"pad.toolbar.strikethrough.title": "Gạch ngang (Ctrl+5)",
"pad.toolbar.ol.title": "Danh sách Có Đánh số (Ctrl+Shift+N)",
"pad.toolbar.ul.title": "Danh sách Không Đánh số (Ctrl+Shift+L)",
"pad.toolbar.indent.title": "Tăng lề (TAB)",
"pad.toolbar.unindent.title": "Giảm lề (Shift+TAB)",
"pad.toolbar.undo.title": "Hoàn tác (Ctrl-Z)",

View File

@ -18,9 +18,9 @@
"pad.toolbar.bold.title": "粗体Ctrl-B",
"pad.toolbar.italic.title": "斜体 (Ctrl-I)",
"pad.toolbar.underline.title": "下划线Ctrl-U",
"pad.toolbar.strikethrough.title": "删除线",
"pad.toolbar.ol.title": "有序列表",
"pad.toolbar.ul.title": "无序列表",
"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)",

View File

@ -14,9 +14,9 @@
"pad.toolbar.bold.title": "粗體Ctrl-B",
"pad.toolbar.italic.title": "斜體Ctrl-I",
"pad.toolbar.underline.title": "底線Ctrl-U",
"pad.toolbar.strikethrough.title": "刪除線",
"pad.toolbar.ol.title": "有序清單",
"pad.toolbar.ul.title": "無序清單",
"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",
@ -94,7 +94,7 @@
"timeslider.toolbar.exportlink.title": "匯出",
"timeslider.exportCurrent": "匯出當前版本為:",
"timeslider.version": "版本{{version}}",
"timeslider.saved": "{{year}}年{{month}}{{day}}日儲存",
"timeslider.saved": "{{year}}年{{month}}{{day}}日儲存",
"timeslider.dateformat": "{{year}}年{{month}}月{{day}}日 {{hours}}:{{minutes}}:{{seconds}}",
"timeslider.month.january": "1月",
"timeslider.month.february": "2月",

View File

@ -575,6 +575,117 @@ exports.deletePad = function(padID, callback)
pad.remove(callback);
});
}
/**
restoreRevision(padID, [rev]) Restores revision from past as new changeset
Example returns:
{code:0, message:"ok", data:null}
{code: 1, message:"padID does not exist", data: null}
*/
exports.restoreRevision = function (padID, rev, callback)
{
var Changeset = require("ep_etherpad-lite/static/js/Changeset");
var padMessage = require("ep_etherpad-lite/node/handler/PadMessageHandler.js");
//check if rev is a number
if (rev !== undefined && typeof rev != "number")
{
//try to parse the number
if (!isNaN(parseInt(rev)))
{
rev = parseInt(rev);
}
else
{
callback(new customError("rev is not a number", "apierror"));
return;
}
}
//ensure this is not a negativ number
if (rev !== undefined && rev < 0)
{
callback(new customError("rev is a negativ number", "apierror"));
return;
}
//ensure this is not a float value
if (rev !== undefined && !is_int(rev))
{
callback(new customError("rev is a float value", "apierror"));
return;
}
//get the pad
getPadSafe(padID, true, function (err, pad)
{
if (ERR(err, callback)) return;
//check if this is a valid revision
if (rev > pad.getHeadRevisionNumber())
{
callback(new customError("rev is higher than the head revision of the pad", "apierror"));
return;
}
pad.getInternalRevisionAText(rev, function (err, atext)
{
if (ERR(err, callback)) return;
var oldText = pad.text();
atext.text += "\n";
function eachAttribRun(attribs, func)
{
var attribsIter = Changeset.opIterator(attribs);
var textIndex = 0;
var newTextStart = 0;
var newTextEnd = atext.text.length;
while (attribsIter.hasNext())
{
var op = attribsIter.next();
var nextIndex = textIndex + op.chars;
if (!(nextIndex <= newTextStart || textIndex >= newTextEnd))
{
func(Math.max(newTextStart, textIndex), Math.min(newTextEnd, nextIndex), op.attribs);
}
textIndex = nextIndex;
}
}
// create a new changeset with a helper builder object
var builder = Changeset.builder(oldText.length);
// assemble each line into the builder
eachAttribRun(atext.attribs, function (start, end, attribs)
{
builder.insert(atext.text.substring(start, end), attribs);
});
var lastNewlinePos = oldText.lastIndexOf('\n');
if (lastNewlinePos < 0)
{
builder.remove(oldText.length - 1, 0);
} else
{
builder.remove(lastNewlinePos, oldText.match(/\n/g).length - 1);
builder.remove(oldText.length - lastNewlinePos - 1, 0);
}
var changeset = builder.toString();
//append the changeset
pad.appendRevision(changeset);
//
padMessage.updatePadClients(pad, function ()
{
});
callback(null, null);
});
});
};
/**
copyPad(sourceID, destinationID[, force=false]) copies a pad. If force is true,

View File

@ -345,10 +345,56 @@ var version =
, "getChatHistory" : ["padID", "start", "end"]
, "getChatHead" : ["padID"]
}
, "1.2.11":
{ "createGroup" : []
, "createGroupIfNotExistsFor" : ["groupMapper"]
, "deleteGroup" : ["groupID"]
, "listPads" : ["groupID"]
, "listAllPads" : []
, "createDiffHTML" : ["padID", "startRev", "endRev"]
, "createPad" : ["padID", "text"]
, "createGroupPad" : ["groupID", "padName", "text"]
, "createAuthor" : ["name"]
, "createAuthorIfNotExistsFor": ["authorMapper" , "name"]
, "listPadsOfAuthor" : ["authorID"]
, "createSession" : ["groupID", "authorID", "validUntil"]
, "deleteSession" : ["sessionID"]
, "getSessionInfo" : ["sessionID"]
, "listSessionsOfGroup" : ["groupID"]
, "listSessionsOfAuthor" : ["authorID"]
, "getText" : ["padID", "rev"]
, "setText" : ["padID", "text"]
, "getHTML" : ["padID", "rev"]
, "setHTML" : ["padID", "html"]
, "getAttributePool" : ["padID"]
, "getRevisionsCount" : ["padID"]
, "getRevisionChangeset" : ["padID", "rev"]
, "getLastEdited" : ["padID"]
, "deletePad" : ["padID"]
, "copyPad" : ["sourceID", "destinationID", "force"]
, "movePad" : ["sourceID", "destinationID", "force"]
, "getReadOnlyID" : ["padID"]
, "getPadID" : ["roID"]
, "setPublicStatus" : ["padID", "publicStatus"]
, "getPublicStatus" : ["padID"]
, "setPassword" : ["padID", "password"]
, "isPasswordProtected" : ["padID"]
, "listAuthorsOfPad" : ["padID"]
, "padUsersCount" : ["padID"]
, "getAuthorName" : ["authorID"]
, "padUsers" : ["padID"]
, "sendClientsMessage" : ["padID", "msg"]
, "listAllGroups" : []
, "checkToken" : []
, "getChatHistory" : ["padID"]
, "getChatHistory" : ["padID", "start", "end"]
, "getChatHead" : ["padID"]
, "restoreRevision" : ["padID", "rev"]
}
};
// set the latest available API version here
exports.latestApiVersion = '1.2.10';
exports.latestApiVersion = '1.2.11';
// exports the versions so it can be used by the new Swagger endpoint
exports.version = version;

View File

@ -37,6 +37,7 @@ var _ = require('underscore');
var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks.js");
var channels = require("channels");
var stats = require('../stats');
var remoteAddress = require("../utils/RemoteAddress").remoteAddress;
/**
* A associative array that saves informations about a session
@ -115,14 +116,16 @@ exports.handleDisconnect = function(client)
//if this connection was already etablished with a handshake, send a disconnect message to the others
if(session && session.author)
{
client.get('remoteAddress', function(er, ip) {
//Anonymize the IP address if IP logging is disabled
if(settings.disableIPlogging) {
ip = 'ANONYMOUS';
}
accessLogger.info('[LEAVE] Pad "'+session.padId+'": Author "'+session.author+'" on client '+client.id+' with IP "'+ip+'" left the pad')
})
// Get the IP address from our persistant object
var ip = remoteAddress[client.id];
// Anonymize the IP address if IP logging is disabled
if(settings.disableIPlogging) {
ip = 'ANONYMOUS';
}
accessLogger.info('[LEAVE] Pad "'+session.padId+'": Author "'+session.author+'" on client '+client.id+' with IP "'+ip+'" left the pad')
//get the author color out of the db
authorManager.getAuthorColorId(session.author, function(err, color)
@ -753,7 +756,13 @@ function handleUserChanges(data, cb)
exports.updatePadClients = function(pad, callback)
{
//skip this step if noone is on this pad
var roomClients = socketio.sockets.clients(pad.id);
var roomClients = [], room = socketio.sockets.adapter.rooms[pad.id];
if (room) {
for (var id in room) {
roomClients.push(socketio.sockets.adapter.nsp.connected[id]);
}
}
if(roomClients.length==0)
return callback();
@ -766,10 +775,8 @@ exports.updatePadClients = function(pad, callback)
var revCache = {};
//go trough all sessions on this pad
async.forEach(roomClients, function(client, callback)
{
async.forEach(roomClients, function(client, callback){
var sid = client.id;
//https://github.com/caolan/async#whilst
//send them all new changesets
async.whilst(
@ -1015,7 +1022,13 @@ function handleClientReady(client, message)
return callback();
//Check if this author is already on the pad, if yes, kick the other sessions!
var roomClients = socketio.sockets.clients(padIds.padId);
var roomClients = [], room = socketio.sockets.adapter.rooms[pad.id];
if (room) {
for (var id in room) {
roomClients.push(socketio.sockets.adapter.nsp.connected[id]);
}
}
for(var i = 0; i < roomClients.length; i++) {
var sinfo = sessioninfos[roomClients[i].id];
if(sinfo && sinfo.author == author) {
@ -1032,19 +1045,19 @@ function handleClientReady(client, message)
sessioninfos[client.id].readonly = padIds.readonly;
//Log creation/(re-)entering of a pad
client.get('remoteAddress', function(er, ip) {
//Anonymize the IP address if IP logging is disabled
if(settings.disableIPlogging) {
ip = 'ANONYMOUS';
}
var ip = remoteAddress[client.id];
if(pad.head > 0) {
accessLogger.info('[ENTER] Pad "'+padIds.padId+'": Client '+client.id+' with IP "'+ip+'" entered the pad');
}
else if(pad.head == 0) {
accessLogger.info('[CREATE] Pad "'+padIds.padId+'": Client '+client.id+' with IP "'+ip+'" created the pad');
}
})
//Anonymize the IP address if IP logging is disabled
if(settings.disableIPlogging) {
ip = 'ANONYMOUS';
}
if(pad.head > 0) {
accessLogger.info('[ENTER] Pad "'+padIds.padId+'": Client '+client.id+' with IP "'+ip+'" entered the pad');
}
else if(pad.head == 0) {
accessLogger.info('[CREATE] Pad "'+padIds.padId+'": Client '+client.id+' with IP "'+ip+'" created the pad');
}
//If this is a reconnect, we don't have to send the client the ClientVars again
if(message.reconnect == true)
@ -1165,7 +1178,14 @@ function handleClientReady(client, message)
client.broadcast.to(padIds.padId).json.send(messageToTheOtherUsers);
//Run trough all sessions of this pad
async.forEach(socketio.sockets.clients(padIds.padId), function(roomClient, callback)
var roomClients = [], room = socketio.sockets.adapter.rooms[pad.id];
if (room) {
for (var id in room) {
roomClients.push(socketio.sockets.adapter.nsp.connected[id]);
}
}
async.forEach(roomClients, function(roomClient, callback)
{
var author;

View File

@ -24,6 +24,7 @@ var log4js = require('log4js');
var messageLogger = log4js.getLogger("message");
var securityManager = require("../db/SecurityManager");
var readOnlyManager = require("../db/ReadOnlyManager");
var remoteAddress = require("../utils/RemoteAddress").remoteAddress;
var settings = require('../utils/Settings');
/**
@ -56,11 +57,15 @@ exports.setSocketIO = function(_socket) {
socket.sockets.on('connection', function(client)
{
// Broken: See http://stackoverflow.com/questions/4647348/send-message-to-specific-client-with-socket-io-and-node-js
// Fixed by having a persistant object, ideally this would actually be in the database layer
// TODO move to database layer
if(settings.trustProxy && client.handshake.headers['x-forwarded-for'] !== undefined){
client.set('remoteAddress', client.handshake.headers['x-forwarded-for']);
remoteAddress[client.id] = client.handshake.headers['x-forwarded-for'];
}
else{
client.set('remoteAddress', client.handshake.address.address);
remoteAddress[client.id] = client.handshake.address;
}
var clientAuthorized = false;

View File

@ -1,10 +1,17 @@
var log4js = require('log4js');
var socketio = require('socket.io');
var settings = require('../../utils/Settings');
var socketIORouter = require("../../handler/SocketIORouter");
var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks");
var webaccess = require("ep_etherpad-lite/node/hooks/express/webaccess");
// there shouldn't be a browser that isn't compatible to all
// transports in this list at once
// e.g. XHR is disabled in IE by default, so in IE it should use jsonp-polling
var socketio = require('socket.io')({
transports: settings.socketTransportProtocols
});
var padMessageHandler = require("../../handler/PadMessageHandler");
var connect = require('connect');
@ -16,7 +23,9 @@ exports.expressCreateServer = function (hook_name, args, cb) {
/* Require an express session cookie to be present, and load the
* session. See http://www.danielbaulig.de/socket-ioexpress for more
* info */
io.set('authorization', function (data, accept) {
io.use(function(socket, accept) {
var data = socket.request;
if (!data.headers.cookie) return accept('No session cookie transmitted.', false);
// Use connect's cookie parser, because it knows how to parse signed cookies
@ -36,35 +45,17 @@ exports.expressCreateServer = function (hook_name, args, cb) {
});
});
// there shouldn't be a browser that isn't compatible to all
// transports in this list at once
// e.g. XHR is disabled in IE by default, so in IE it should use jsonp-polling
io.set('transports', settings.socketTransportProtocols );
var socketIOLogger = log4js.getLogger("socket.io");
io.set('logger', {
debug: function (str)
{
socketIOLogger.debug.apply(socketIOLogger, arguments);
},
info: function (str)
{
socketIOLogger.info.apply(socketIOLogger, arguments);
},
warn: function (str)
{
socketIOLogger.warn.apply(socketIOLogger, arguments);
},
error: function (str)
{
socketIOLogger.error.apply(socketIOLogger, arguments);
},
});
// var socketIOLogger = log4js.getLogger("socket.io");
// Debug logging now has to be set at an environment level, this is stupid.
// https://github.com/Automattic/socket.io/wiki/Migrating-to-1.0
// This debug logging environment is set in Settings.js
//minify socket.io javascript
if(settings.minify)
io.enable('browser client minification');
// Due to a shitty decision by the SocketIO team minification is
// no longer available, details available at:
// http://stackoverflow.com/questions/23981741/minify-socket-io-socket-io-js-with-1-0
// if(settings.minify) io.enable('browser client minification');
//Initalize the Socket.IO Router
socketIORouter.setSocketIO(io);
socketIORouter.addComponent("pad", padMessageHandler);

View File

@ -16,8 +16,6 @@
var jsdom = require('jsdom-nocontextifiy').jsdom;
var log4js = require('log4js');
var Changeset = require("ep_etherpad-lite/static/js/Changeset");
var contentcollector = require("ep_etherpad-lite/static/js/contentcollector");

View File

@ -0,0 +1 @@
exports.remoteAddress = {};

View File

@ -228,6 +228,7 @@ exports.reloadSettings = function reloadSettings() {
log4js.configure(exports.logconfig);//Configure the logging appenders
log4js.setGlobalLogLevel(exports.loglevel);//set loglevel
process.env['DEBUG'] = 'socket.io:' + exports.loglevel; // Used by SocketIO for Debug
log4js.replaceConsole();
if(!exports.sessionKey){ // If the secretKey isn't set we also create yet another unique value here

View File

@ -15,9 +15,9 @@
"request" : "2.9.100",
"require-kernel" : "1.0.5",
"resolve" : ">=1.0.0",
"socket.io" : "0.9.x",
"ueberDB" : ">=0.2.2",
"express" : "3.1.0",
"socket.io" : ">=1.2.0",
"ueberDB" : ">=0.2.9",
"express" : ">3.1.0 <3.9.0",
"async" : "0.1.x",
"connect" : "2.7.x",
"clean-css" : "0.3.2",
@ -34,7 +34,7 @@
"semver" : ">2.3.0",
"security" : "1.0.0",
"tinycon" : "0.0.1",
"underscore" : "1.3.1",
"underscore" : "1.5.1",
"unorm" : "1.0.0",
"languages4translatewiki" : "0.1.3",
"swagger-node-express" : ">=2.1.0",

View File

@ -59,7 +59,7 @@ a img {
height: 32px;
}
.toolbar ul {
position: relative;
position: absolute;
list-style: none;
padding-right: 3px;
padding-left: 1px;
@ -67,9 +67,6 @@ a img {
overflow: hidden;
float: left
}
.toolbar ul.menu_right {
float: right
}
.toolbar ul li {
float: left;
margin-left: 2px;
@ -84,6 +81,7 @@ a img {
visibility: hidden;
width: 0px;
padding: 5px;
height:20px;
}
.toolbar ul li a:hover {
text-decoration: none;
@ -164,6 +162,15 @@ a img {
border: 1px solid #ccc;
outline: none;
}
.toolbar ul.menu_left {
left:0px;
right:250px;
}
.toolbar ul.menu_right {
right:0px;
}
li[data-key=showusers] > a {
min-width: 30px;
text-align: left;
@ -175,6 +182,9 @@ li[data-key=showusers] > a #online_count {
top: 2px;
padding-left: 2px;
}
#editbar{
display:none;
}
#editorcontainer {
position: absolute;
top: 37px; /* + 1px border */
@ -843,12 +853,16 @@ input[type=checkbox] {
width: 185px !important;
}
@media screen and (max-width: 600px) {
.toolbar ul li.separator {
display: none;
}
.toolbar ul li a {
padding: 4px 1px
}
.toolbar ul li.separator {
display: none;
}
.toolbar ul li a {
padding: 4px 1px
}
.toolbar ul.menu_left {
left:0px;
right:150px;
}
}
@media all and (max-width: 400px){
#gritter-notice-wrapper{
@ -894,9 +908,13 @@ input[type=checkbox] {
#editbar {
height: 62px;
}
.toolbar ul.menu_left {
left:0px;
right:100px;
}
.toolbar ul.menu_right {
float: left;
margin-top:2px;
right:0px;
}
.popup {
width:100%;
@ -917,6 +935,9 @@ input[type=checkbox] {
#editorcontainer {
margin-bottom: 33px
}
.toolbar ul.menu_left {
right:0px;
}
.toolbar ul.menu_right {
background: #f7f7f7;
background: -webkit-linear-gradient(#f7f7f7, #f1f1f1 80%);
@ -1076,4 +1097,4 @@ input[type=checkbox] {
text-shadow: none;
}
/* End of gritter stuff */
/* End of gritter stuff */

View File

@ -173,6 +173,7 @@
#import_export {
top: 115px;
width: 185px;
position: fixed;
}
.timeslider-bar {
background: #f7f7f7;

View File

@ -152,7 +152,6 @@ function Ace2Inner(){
var dmesg = noop;
window.dmesg = noop;
var scheduler = parent; // hack for opera required
var textFace = 'monospace';
@ -597,6 +596,13 @@ function Ace2Inner(){
fixView();
});
}, 0);
// Chrome can't handle the truth.. If CSS rule white-space:pre-wrap
// is true then any paste event will insert two lines..
if(browser.chrome){
$("#innerdocbody").css({"white-space":"normal"});
}
}
function setStyled(newVal)
@ -3749,7 +3755,7 @@ function Ace2Inner(){
toggleAttributeOnSelection('strikethrough');
specialHandled = true;
}
if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which) == "L" && (evt.metaKey || evt.ctrlKey))
if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "l" && (evt.metaKey || evt.ctrlKey) && evt.shiftKey)
{
// cmd-shift-L (unorderedlist)
fastIncorp(9);
@ -3757,7 +3763,7 @@ function Ace2Inner(){
doInsertUnorderedList()
specialHandled = true;
}
if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which) == "N" && (evt.metaKey || evt.ctrlKey))
if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "n" && (evt.metaKey || evt.ctrlKey) && evt.shiftKey)
{
// cmd-shift-N (orderedlist)
fastIncorp(9);
@ -3765,6 +3771,12 @@ function Ace2Inner(){
doInsertOrderedList()
specialHandled = true;
}
if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "c" && (evt.metaKey || evt.ctrlKey) && evt.shiftKey) {
// cmd-shift-C (clearauthorship)
fastIncorp(9);
evt.preventDefault();
CMDS.clearauthorship();
}
if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "h" && (evt.ctrlKey))
{
// cmd-H (backspace)
@ -3816,7 +3828,7 @@ function Ace2Inner(){
}
updateBrowserSelectionFromRep();
var myselection = document.getSelection(); // get the current caret selection, can't use rep. here because that only gives us the start position not the current
var caretOffsetTop = myselection.focusNode.parentNode.offsetTop | myselection.focusNode.offsetTop; // get the carets selection offset in px IE 214
var caretOffsetTop = myselection.focusNode.parentNode.offsetTop || myselection.focusNode.offsetTop; // get the carets selection offset in px IE 214
// top.console.log(caretOffsetTop);
setScrollY(caretOffsetTop); // set the scrollY offset of the viewport on the document

View File

@ -89,7 +89,7 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
function textify(str)
{
return sanitizeUnicode(
str.replace(/[\n\r ]/g, ' ').replace(/\xa0/g, ' ').replace(/\t/g, ' '));
str.replace(/\n/g, '').replace(/[\n\r ]/g, ' ').replace(/\xa0/g, ' ').replace(/\t/g, ' '));
}
function getAssoc(node, name)

View File

@ -67,7 +67,7 @@ function createCookie(name, value, days, path){ /* Warning Internet Explorer doe
}
//Check if the browser is IE and if so make sure the full path is set in the cookie
if(navigator.appName=='Microsoft Internet Explorer'){
if((navigator.appName == 'Microsoft Internet Explorer') || ((navigator.appName == 'Netscape') && (new RegExp("Trident/.*rv:([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) != null))){
document.cookie = name + "=" + value + expires + "; path="+document.location;
}
else{
@ -937,4 +937,3 @@ exports.handshake = handshake;
exports.pad = pad;
exports.init = init;
exports.alertBar = alertBar;

View File

@ -140,7 +140,12 @@ var padeditbar = (function()
init: function() {
var self = this;
self.dropdowns = [];
// Listen for resize events (sucks but needed as iFrame ace_inner has to be position absolute
// A CSS fix for this would be nice but I'm not sure how we'd do it.
$(window).resize(function(){
self.redrawHeight();
});
$("#editbar .editbarbutton").attr("unselectable", "on"); // for IE
$("#editbar").removeClass("disabledtoolbar").addClass("enabledtoolbar");
$("#editbar [data-key]").each(function () {
@ -149,6 +154,10 @@ var padeditbar = (function()
});
});
$('#editbar').show();
this.redrawHeight();
registerDefaultCommands(self);
hooks.callAll("postToolbarInit", {
@ -170,6 +179,12 @@ var padeditbar = (function()
this.commands[cmd] = callback;
return this;
},
redrawHeight: function(){
var editbarHeight = $('.menu_left').height() + 2 + "px";
var containerTop = $('.menu_left').height() + 5 + "px";
$('#editbar').css("height", editbarHeight);
$('#editorcontainer').css("top", containerTop);
},
registerDropdownCommand: function (cmd, dropdown) {
dropdown = dropdown || cmd;
self.dropdowns.push(dropdown)

View File

@ -55,7 +55,7 @@ function createCookie(name, value, days, path){ /* Used by IE */
}
//Check if the browser is IE and if so make sure the full path is set in the cookie
if(navigator.appName=='Microsoft Internet Explorer'){
if((navigator.appName == 'Microsoft Internet Explorer') || ((navigator.appName == 'Netscape') && (new RegExp("Trident/.*rv:([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) != null))){
document.cookie = name + "=" + value + expires + "; path=/"; /* Note this bodge fix for IE is temporary until auth is rewritten */
}
else{
@ -482,7 +482,7 @@ var padutils = {
},
bindCheckboxChange: function(node, func)
{
$(node).bind("click change", func);
$(node).change(func);
},
encodeUserId: function(userId)
{

View File

@ -1,6 +1,7 @@
var plugins = require("ep_etherpad-lite/static/js/pluginfw/plugins");
var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks");
var npm = require("npm");
var request = require("request");
var npmIsLoaded = false;
var withNpm = function (npmfn) {
@ -60,17 +61,15 @@ exports.availablePlugins = null;
var cacheTimestamp = 0;
exports.getAvailablePlugins = function(maxCacheAge, cb) {
withNpm(function (er) {
request("http://etherpad.org/plugins.json", function(er, response, plugins){
if (er) return cb && cb(er);
if(exports.availablePlugins && maxCacheAge && Math.round(+new Date/1000)-cacheTimestamp <= maxCacheAge) {
return cb && cb(null, exports.availablePlugins)
}
npm.commands.search(['ep_'], /*silent?*/true, function(er, results) {
if(er) return cb && cb(er);
exports.availablePlugins = results;
cacheTimestamp = Math.round(+new Date/1000);
cb && cb(null, results)
})
plugins = JSON.parse(plugins);
exports.availablePlugins = plugins;
cacheTimestamp = Math.round(+new Date/1000);
cb && cb(null, plugins)
});
};

View File

@ -11,31 +11,31 @@ describe("Language select and change", function(){
helper.newPad(cb);
this.timeout(60000);
});
// Destroy language cookies
it("makes text german", function(done) {
var inner$ = helper.padInner$;
var chrome$ = helper.padChrome$;
//click on the settings button to make settings visible
var $settingsButton = chrome$(".buttonicon-settings");
$settingsButton.click();
//click the language button
var $language = chrome$("#languagemenu");
var $languageoption = $language.find("[value=de]");
//select german
$languageoption.attr('selected','selected');
$language.change();
helper.waitFor(function() {
helper.waitFor(function() {
return chrome$(".buttonicon-bold").parent()[0]["title"] == "Fett (Strg-B)";
})
.done(function(){
//get the value of the bold button
var $boldButton = chrome$(".buttonicon-bold").parent();
//get the title of the bold button
var boldButtonTitle = $boldButton[0]["title"];
@ -44,58 +44,58 @@ describe("Language select and change", function(){
done();
});
});
it("makes text English", function(done) {
var inner$ = helper.padInner$;
var chrome$ = helper.padChrome$;
//click on the settings button to make settings visible
var $settingsButton = chrome$(".buttonicon-settings");
$settingsButton.click();
//click the language button
var $language = chrome$("#languagemenu");
//select english
$language.val("en");
$language.change();
//get the value of the bold button
var $boldButton = chrome$(".buttonicon-bold").parent();
helper.waitFor(function() { return $boldButton[0]["title"] != "Fett (Strg-B)";})
helper.waitFor(function() { return $boldButton[0]["title"] != "Fett (Strg+B)";})
.done(function(){
//get the value of the bold button
var $boldButton = chrome$(".buttonicon-bold").parent();
//get the title of the bold button
var boldButtonTitle = $boldButton[0]["title"];
//check if the language is now English
expect(boldButtonTitle).to.be("Bold (Ctrl-B)");
expect(boldButtonTitle).to.be("Bold (Ctrl+B)");
done();
});
});
it("changes direction when picking an rtl lang", function(done) {
var inner$ = helper.padInner$;
var chrome$ = helper.padChrome$;
//click on the settings button to make settings visible
var $settingsButton = chrome$(".buttonicon-settings");
$settingsButton.click();
//click the language button
var $language = chrome$("#languagemenu");
var $languageoption = $language.find("[value=ar]");
//select arabic
// $languageoption.attr('selected','selected'); // Breaks the test..
$language.val("ar");
$languageoption.change();
helper.waitFor(function() {
helper.waitFor(function() {
return chrome$("html")[0]["dir"] != 'ltr';
})
.done(function(){