Merge remote-tracking branch 'refs/remotes/origin/master' into develop

# Conflicts:
#	src/search.js
This commit is contained in:
Baris Usakli
2017-07-28 14:19:09 -04:00
36 changed files with 270 additions and 194 deletions

2
nodebb
View File

@@ -308,7 +308,7 @@ var commands = {
process.stdout.write(' "' + './nodebb restart'.yellow + '" to restart NodeBB\n\n'.reset); process.stdout.write(' "' + './nodebb restart'.yellow + '" to restart NodeBB\n\n'.reset);
// Spawn a new NodeBB process // Spawn a new NodeBB process
cproc.fork(loaderPath, { cproc.fork(loaderPath, process.argv.slice(3), {
env: process.env, env: process.env,
}); });
}, },

View File

@@ -2,7 +2,7 @@
"name": "nodebb", "name": "nodebb",
"license": "GPL-3.0", "license": "GPL-3.0",
"description": "NodeBB Forum", "description": "NodeBB Forum",
"version": "1.5.2", "version": "1.5.3",
"homepage": "http://www.nodebb.org", "homepage": "http://www.nodebb.org",
"repository": { "repository": {
"type": "git", "type": "git",
@@ -55,19 +55,19 @@
"morgan": "^1.3.2", "morgan": "^1.3.2",
"mousetrap": "^1.5.3", "mousetrap": "^1.5.3",
"nconf": "~0.8.2", "nconf": "~0.8.2",
"nodebb-plugin-composer-default": "5.0.3", "nodebb-plugin-composer-default": "5.0.5",
"nodebb-plugin-dbsearch": "2.0.6", "nodebb-plugin-dbsearch": "2.0.6",
"nodebb-plugin-emoji-extended": "1.1.1", "nodebb-plugin-emoji-extended": "1.1.1",
"nodebb-plugin-emoji-one": "1.2.1", "nodebb-plugin-emoji-one": "1.2.1",
"nodebb-plugin-markdown": "8.0.0", "nodebb-plugin-markdown": "8.0.3",
"nodebb-plugin-mentions": "2.1.5", "nodebb-plugin-mentions": "2.1.5",
"nodebb-plugin-soundpack-default": "1.0.0", "nodebb-plugin-soundpack-default": "1.0.0",
"nodebb-plugin-spam-be-gone": "0.5.0", "nodebb-plugin-spam-be-gone": "0.5.0",
"nodebb-rewards-essentials": "0.0.9", "nodebb-rewards-essentials": "0.0.9",
"nodebb-theme-lavender": "4.0.5", "nodebb-theme-lavender": "4.0.5",
"nodebb-theme-persona": "5.0.14", "nodebb-theme-persona": "5.0.16",
"nodebb-theme-slick": "1.1.0", "nodebb-theme-slick": "1.1.0",
"nodebb-theme-vanilla": "6.0.11", "nodebb-theme-vanilla": "6.0.13",
"nodebb-widget-essentials": "3.0.1", "nodebb-widget-essentials": "3.0.1",
"nodemailer": "2.6.4", "nodemailer": "2.6.4",
"nodemailer-sendmail-transport": "1.0.0", "nodemailer-sendmail-transport": "1.0.0",

View File

@@ -1,11 +1,11 @@
{ {
"checking-for-installed": "Vyhledávání nainstalovaných motivů…", "checking-for-installed": "Vyhledávání nainstalovaných motivů…",
"homepage": "Homepage", "homepage": "Domovská stránka",
"select-theme": "Select Theme", "select-theme": "Vybrat motiv",
"current-theme": "Current Theme", "current-theme": "Aktuální motiv",
"no-themes": "No installed themes found", "no-themes": "Žádný nainstalovaný motiv nebyl nalezen",
"revert-confirm": "Are you sure you wish to restore the default NodeBB theme?", "revert-confirm": "Jste si jist/a, že chcete obnovit výchozí motiv NodeBB?",
"theme-changed": "Theme Changed", "theme-changed": "Motiv byl změněn",
"revert-success": "You have successfully reverted your NodeBB back to it's default theme.", "revert-success": "Úspěšně jste vrátil/a NodeBB na výchozí motiv",
"restart-to-activate": "Please restart your NodeBB to fully activate this theme" "restart-to-activate": "Restartujte prosím NodeBB, aby mohl být plně aktivován tento motiv"
} }

View File

@@ -13,7 +13,9 @@
"disable-email-changes": "Disable email changes", "disable-email-changes": "Disable email changes",
"disable-password-changes": "Disable password changes", "disable-password-changes": "Disable password changes",
"allow-account-deletion": "Allow account deletion", "allow-account-deletion": "Allow account deletion",
"user-info-private": "Make user info private", "user-info-private": "Hide user list and data from guests",
"hide-fullname": "Hide fullname from users",
"hide-email": "Hide email from users",
"themes": "Themes", "themes": "Themes",
"disable-user-skins": "Prevent users from choosing a custom skin", "disable-user-skins": "Prevent users from choosing a custom skin",
"account-protection": "Account Protection", "account-protection": "Account Protection",

View File

@@ -1,16 +1,16 @@
{ {
"section-general": "General", "section-general": "General",
"general/dashboard": "Dashboard", "general/dashboard": "Dashboard",
"general/homepage": "Home Page", "general/homepage": "דף הבית",
"general/navigation": "Navigation", "general/navigation": "ניווט",
"general/languages": "Languages", "general/languages": "שפות",
"general/sounds": "Sounds", "general/sounds": "Sounds",
"general/social": "Social", "general/social": "Social",
"section-manage": "Manage", "section-manage": "Manage",
"manage/categories": "Categories", "manage/categories": "קטגוריות",
"manage/tags": "Tags", "manage/tags": "תגיות",
"manage/users": "Users", "manage/users": "משתמשים",
"manage/registration": "Registration Queue", "manage/registration": "Registration Queue",
"manage/groups": "Groups", "manage/groups": "Groups",
"manage/ip-blacklist": "IP Blacklist", "manage/ip-blacklist": "IP Blacklist",
@@ -21,10 +21,10 @@
"settings/email": "Email", "settings/email": "Email",
"settings/user": "User", "settings/user": "User",
"settings/group": "Group", "settings/group": "Group",
"settings/guest": "Guests", "settings/guest": "אורח",
"settings/uploads": "Uploads", "settings/uploads": "Uploads",
"settings/post": "Post", "settings/post": "Post",
"settings/chat": "Chat", "settings/chat": "צ'אט",
"settings/pagination": "Pagination", "settings/pagination": "Pagination",
"settings/tags": "Tags", "settings/tags": "Tags",
"settings/notifications": "Notifications", "settings/notifications": "Notifications",

View File

@@ -1,7 +1,7 @@
{ {
"alert.confirm-reload": "Are you sure you wish to reload NodeBB?", "alert.confirm-reload": "Biztosan szeretnéd újratölteni a NodeBB-t?",
"alert.confirm-restart": "Are you sure you wish to restart NodeBB?", "alert.confirm-restart": "Biztosan szeretnéd újraindítani a NodeBB-t?",
"acp-title": "%1 | NodeBB Admin Control Panel", "acp-title": "%1 | NodeBB Admin Kezelőpanel",
"settings-header-contents": "Contents" "settings-header-contents": "Tartalmak"
} }

View File

@@ -1,11 +1,11 @@
{ {
"post-cache": "Post Cache", "post-cache": "Bejegyzés Gyorsítótár",
"posts-in-cache": "Posts in Cache", "posts-in-cache": "Bejegyzések a Gyorsítótárban",
"average-post-size": "Average Post Size", "average-post-size": "Átlagos Bejegyzés Méret",
"length-to-max": "Length / Max", "length-to-max": "Hossz / Max",
"percent-full": "%1% Full", "percent-full": "%1% Tele",
"post-cache-size": "Post Cache Size", "post-cache-size": "Bejegyzés Gyorsítótár Mérete",
"items-in-cache": "Items in Cache", "items-in-cache": "Elemek a Gyorsítótárban",
"control-panel": "Control Panel", "control-panel": "Kezelőpanel",
"update-settings": "Update Cache Settings" "update-settings": "Gyorsítótár Beállítások Frissítése"
} }

View File

@@ -2,35 +2,35 @@
"x-b": "%1 b", "x-b": "%1 b",
"x-mb": "%1 mb", "x-mb": "%1 mb",
"x-gb": "%1 gb", "x-gb": "%1 gb",
"uptime-seconds": "Uptime in Seconds", "uptime-seconds": "Működési Idő Másodpercben",
"uptime-days": "Uptime in Days", "uptime-days": "Működési Idő Napban",
"mongo": "Mongo", "mongo": "Mongo",
"mongo.version": "MongoDB Version", "mongo.version": "MongoDB Verzió",
"mongo.storage-engine": "Storage Engine", "mongo.storage-engine": "Tároló Motor",
"mongo.collections": "Collections", "mongo.collections": "Gyűjtemények",
"mongo.objects": "Objects", "mongo.objects": "Tárgyak",
"mongo.avg-object-size": "Avg. Object Size", "mongo.avg-object-size": "Átl. Tárgy Méret",
"mongo.data-size": "Data Size", "mongo.data-size": "Data Size",
"mongo.storage-size": "Storage Size", "mongo.storage-size": "Storage Size",
"mongo.index-size": "Index Size", "mongo.index-size": "Index Size",
"mongo.file-size": "File Size", "mongo.file-size": "File Size",
"mongo.resident-memory": "Resident Memory", "mongo.resident-memory": "Rezidens Memória",
"mongo.virtual-memory": "Virtual Memory", "mongo.virtual-memory": "Virtuális Memória",
"mongo.mapped-memory": "Mapped Memory", "mongo.mapped-memory": "Leképezett Memória",
"mongo.raw-info": "MongoDB Raw Info", "mongo.raw-info": "MongoDB Nyers Infó",
"redis": "Redis", "redis": "Redis",
"redis.version": "Redis Version", "redis.version": "Redis Verzió",
"redis.connected-clients": "Connected Clients", "redis.connected-clients": "Connected Clients",
"redis.connected-slaves": "Connected Slaves", "redis.connected-slaves": "Connected Slaves",
"redis.blocked-clients": "Blocked Clients", "redis.blocked-clients": "Blocked Clients",
"redis.used-memory": "Used Memory", "redis.used-memory": "Használt Memória",
"redis.memory-frag-ratio": "Memory Fragmentation Ratio", "redis.memory-frag-ratio": "Memory Fragmentation Ratio",
"redis.total-connections-recieved": "Total Connections Received", "redis.total-connections-recieved": "Total Connections Received",
"redis.total-commands-processed": "Total Commands Processed", "redis.total-commands-processed": "Total Commands Processed",
"redis.iops": "Instantaneous Ops. Per Second", "redis.iops": "Pillanatnyi Műv. Másodpercenként",
"redis.keyspace-hits": "Keyspace Hits", "redis.keyspace-hits": "Keyspace Hits",
"redis.keyspace-misses": "Keyspace Misses", "redis.keyspace-misses": "Keyspace Misses",
"redis.raw-info": "Redis Raw Info" "redis.raw-info": "Redis Nyers Infó"
} }

View File

@@ -1,6 +1,6 @@
{ {
"general": "Általános", "general": "Általános",
"private-groups": "Private Groups", "private-groups": "Privát Csoportok",
"private-groups.help": "If enabled, joining of groups requires the approval of the group owner <em>(Default: enabled)</em>", "private-groups.help": "If enabled, joining of groups requires the approval of the group owner <em>(Default: enabled)</em>",
"private-groups.warning": "<strong>Beware!</strong> If this option is disabled and you have private groups, they automatically become public.", "private-groups.warning": "<strong>Beware!</strong> If this option is disabled and you have private groups, they automatically become public.",
"allow-creation": "Allow Group Creation", "allow-creation": "Allow Group Creation",

View File

@@ -32,9 +32,9 @@
"notif.post.unsub.info": "Ez a hozzászólás-értesítés a feliratkozási beállításaid miatt lett kiküldve.", "notif.post.unsub.info": "Ez a hozzászólás-értesítés a feliratkozási beállításaid miatt lett kiküldve.",
"test.text1": "Ez egy teszt levél, ami által ellenőrizzük, hogy a levelező helyesen lett beállítva a NodeBB-ben.", "test.text1": "Ez egy teszt levél, ami által ellenőrizzük, hogy a levelező helyesen lett beállítva a NodeBB-ben.",
"unsub.cta": "Kattintson ide a beállítások módosításához", "unsub.cta": "Kattintson ide a beállítások módosításához",
"banned.subject": "You have been banned from %1", "banned.subject": "Ki lettél tiltva a(z) %1 oldalról",
"banned.text1": "The user %1 has been banned from %2.", "banned.text1": "%1 nevű felhasználó ki lett tiltva a(z) %2 oldalról.",
"banned.text2": "This ban will last until %1.", "banned.text2": "A kitiltás %1-ig fog tartani.",
"banned.text3": "This is the reason why you have been banned:", "banned.text3": "Az ok, amiért ki lettél tiltva:",
"closing": "Köszönjük!" "closing": "Köszönjük!"
} }

View File

@@ -1,5 +1,5 @@
{ {
"alert.confirm-reload": "คุณต้องการโหลดการทำงาน NodeBB อีกครั้งหรือไม่?", "alert.confirm-reload": "คุณต้องการโหลด NodeBB อีกครั้งหรือไม่?",
"alert.confirm-restart": "คุณต้องการเริ่มการทำงาน NodeBB ใหม่หรือไม่?", "alert.confirm-restart": "คุณต้องการเริ่มการทำงาน NodeBB ใหม่หรือไม่?",
"acp-title": "%1 | แผงควบคุมของผู้ดูแลระบบ", "acp-title": "%1 | แผงควบคุมของผู้ดูแลระบบ",

View File

@@ -6,31 +6,31 @@
"uptime-days": "ระยะเวลาทำงานต่อเนื่องเป็นวัน", "uptime-days": "ระยะเวลาทำงานต่อเนื่องเป็นวัน",
"mongo": "Mongo", "mongo": "Mongo",
"mongo.version": "รุ่น MongoDB", "mongo.version": "MongoDB เวอร์ชั่น",
"mongo.storage-engine": "เอ็นจินการจัดเก็บ", "mongo.storage-engine": "ระบบการจัดเก็บ",
"mongo.collections": "คอลเลคชัน", "mongo.collections": "คอลเลคชัน",
"mongo.objects": "ออพเจ็กท์", "mongo.objects": "ออพเจ็กท์",
"mongo.avg-object-size": "ขนาดออพเจ็กท์โดยเฉลี่ย", "mongo.avg-object-size": "ขนาดออพเจ็กท์โดยเฉลี่ย",
"mongo.data-size": "ขนาดข้อมูล", "mongo.data-size": "ขนาดข้อมูล",
"mongo.storage-size": "ขนาดพื้นที่ข้อมูล", "mongo.storage-size": "ขนาดพื้นที่จัดเก็บ",
"mongo.index-size": "ขนาดดัชนี", "mongo.index-size": "ขนาดดัชนี",
"mongo.file-size": "ขนาดไฟล์", "mongo.file-size": "ขนาดไฟล์",
"mongo.resident-memory": "Resident Memory", "mongo.resident-memory": "หน่วยความจำถาวร",
"mongo.virtual-memory": "Virtual Memory", "mongo.virtual-memory": "หน่วยความจำเสมือน",
"mongo.mapped-memory": "Mapped Memory", "mongo.mapped-memory": "เส้นทางหน่วยความจำ",
"mongo.raw-info": "ข้อมูลดิบของ MongoDB", "mongo.raw-info": "ข้อมูลดิบของ MongoDB",
"redis": "Redis", "redis": "Redis",
"redis.version": "รุ่นของ Redis", "redis.version": "Redis เวอร์ชั่น",
"redis.connected-clients": "Connected Clients", "redis.connected-clients": "ไคลเอ็นท์ที่เชื่อมต่อแล้ว",
"redis.connected-slaves": "Connected Slaves", "redis.connected-slaves": "Slaves ที่เชื่อมต่อแล้ว",
"redis.blocked-clients": "ไคลเอ็นท์ที่ถูกบล็อค", "redis.blocked-clients": "ไคลเอ็นท์ที่ถูกบล็อค",
"redis.used-memory": "หน่วยความจำที่ถูกใช้", "redis.used-memory": "หน่วยความจำที่ถูกใช้",
"redis.memory-frag-ratio": "Memory Fragmentation Ratio", "redis.memory-frag-ratio": "อัตราการกระจายตัวของหน่วยความจำ",
"redis.total-connections-recieved": "การเชื่อมต่อที่ได้รับทั้งหมด", "redis.total-connections-recieved": "การเชื่อมต่อที่ได้รับทั้งหมด",
"redis.total-commands-processed": "คำสั่งที่ประมวลผลแล้วทั้งหมด", "redis.total-commands-processed": "คำสั่งที่ประมวลผลแล้วทั้งหมด",
"redis.iops": "การทำงานพร้อมกันต่อวินาที", "redis.iops": "การทำงานพร้อมกันต่อวินาที",
"redis.keyspace-hits": "Keyspace Hits", "redis.keyspace-hits": "Keyspace Hits",
"redis.keyspace-misses": "Keyspace Misses", "redis.keyspace-misses": "Keyspace Misses",
"redis.raw-info": "Redis Raw Info" "redis.raw-info": "ข้อมูลดิบของ Redis"
} }

View File

@@ -1,14 +1,14 @@
{ {
"figure-x": "Figure %1", "figure-x": "การปรับแต่ง %1",
"error-events-per-day": "<code>%1</code> events per day", "error-events-per-day": "<code>%1</code> อีเวนท์ต่อวัน",
"error.404": "404 Not Found", "error.404": "404 ไม่พบเพจ",
"error.503": "503 Service Unavailable", "error.503": "503 เซอร์วิสไม่พร้อมใช้งาน",
"manage-error-log": "Manage Error Log", "manage-error-log": "จัดการผลบันทึกความผิดพลาด",
"export-error-log": "Export Error Log (CSV)", "export-error-log": "นำออกผลบันทึกความผิดพลาด (CSV)",
"clear-error-log": "Clear Error Log", "clear-error-log": "ล้างผลบันทึกความผิดพลาด",
"route": "Route", "route": "เส้นทาง",
"count": "Count", "count": "นับจำนวน",
"no-routes-not-found": "Hooray! No 404 errors!", "no-routes-not-found": "เอาแล้วซิ! พบความผิดพลาดรหัส 404",
"clear404-confirm": "Are you sure you wish to clear the 404 error logs?", "clear404-confirm": "คุณแน่ใจแล้วใช่ไหมว่าต้องการล้างผลบันทึกความผิดพลาดรหัส 404?",
"clear404-success": "\"404 Not Found\" errors cleared" "clear404-success": "บันทึกความผิดพลาด \"404 ไม่พบเพจ\" ถูกล้างเรียบร้อยแล้ว"
} }

View File

@@ -1,6 +1,6 @@
{ {
"events": "Events", "events": "อีเวนท์",
"no-events": "There are no events", "no-events": "ไม่มีอีเวนท์",
"control-panel": "Events Control Panel", "control-panel": "แผงควบคุมอีเวนท์",
"delete-events": "Delete Events" "delete-events": "ลบอีเวนท์"
} }

View File

@@ -1,7 +1,7 @@
{ {
"logs": "Logs", "logs": "บันทึกผลกิจกรรม",
"control-panel": "Logs Control Panel", "control-panel": "แผงควบคุมบันทึกผลกิจกรรม",
"reload": "Reload Logs", "reload": "โหลดบันทึกผลกิจกรรมอีกครั้ง",
"clear": "Clear Logs", "clear": "ล้างบันทึกผลกิจกรรม",
"clear-success": "Logs Cleared!" "clear-success": "ล้างบันทึกผลกิจกรรมแล้ว!"
} }

View File

@@ -1,12 +1,12 @@
{ {
"custom-css": "Custom CSS", "custom-css": "ปรับแต่ง CSS",
"custom-css.description": "Enter your own CSS declarations here, which will be applied after all other styles.", "custom-css.description": "ใส่ CSS ของคุณที่นี่, มันจะถูกนำไปใช้ต่อจากสไตล์อื่นๆ",
"custom-css.enable": "Enable Custom CSS", "custom-css.enable": "เปิดการปรับแต่ง CSS",
"custom-header": "Custom Header", "custom-header": "ปรับแต่งส่วนหัว",
"custom-header.description": "Enter custom HTML here (ex. JavaScript, Meta Tags, etc.), which will be appended to the <code>&lt;head&gt;</code> section of your forum's markup.", "custom-header.description": "ใส่การปรับแต่ง HTML ที่นี่ (เช่น JavaScript, Meta Tags หรืออื่นๆ) , มันจะถูกเพิ่มใน <code>&lt;head&gt;</code>ของส่วนฟอรั่มของคุณ",
"custom-header.enable": "Enable Custom Header", "custom-header.enable": "เปิดการปรับแต่งส่วนหัว",
"custom-css.livereload": "Enable Live Reload", "custom-css.livereload": "เปิดการบังคับให้มีผลในทันที",
"custom-css.livereload.description": "Enable this to force all sessions on every device under your account to refresh whenever you click save" "custom-css.livereload.description": "การเปิดนี้จะบังคับทุกเซสชั่นบนทุกอุปกรณ์ภายใต้บัญชีของคุณให้ถูกรีเฟรชทันทีที่คุณกดบันทึก"
} }

View File

@@ -1,9 +1,9 @@
{ {
"loading": "Loading Skins...", "loading": "กำลังโหลดหน้ากาก",
"homepage": "Homepage", "homepage": "หน้าแรก",
"select-skin": "Select Skin", "select-skin": "เลือกหน้ากาก",
"current-skin": "Current Skin", "current-skin": "หน้ากากปัจจุบัน",
"skin-updated": "Skin Updated", "skin-updated": "หน้ากากถูกอัปเดทแล้ว",
"applied-success": "%1 skin was succesfully applied", "applied-success": "%1 หน้ากากถูกใช้เสร็จสิ้นแล้ว",
"revert-success": "Skin reverted to base colours" "revert-success": "หน้ากากถูกทำให้ย้อนกลับไปใช้สีพื้นฐานแล้ว"
} }

View File

@@ -1,11 +1,11 @@
{ {
"checking-for-installed": "Checking for installed themes...", "checking-for-installed": "กำลังตรวจสอบธีมที่ถูกติดตั้งแล้ว",
"homepage": "Homepage", "homepage": "หน้าแรก",
"select-theme": "Select Theme", "select-theme": "เลือกธีม",
"current-theme": "Current Theme", "current-theme": "ธีมปัจจุบัน",
"no-themes": "No installed themes found", "no-themes": "ไม่พบธีมที่ถูกติดตั้งแล้ว",
"revert-confirm": "Are you sure you wish to restore the default NodeBB theme?", "revert-confirm": "คุณแน่ใจแล้วใช่ไหมที่ต้องการกลับไปใช้ธีมพื้นฐานของ NodeBB?",
"theme-changed": "Theme Changed", "theme-changed": "ธีมถูกเปลี่ยนแล้ว",
"revert-success": "You have successfully reverted your NodeBB back to it's default theme.", "revert-success": "คุณได้ทำการเปลี่ยน NodeBB ของคุณให้กลับไปใช้ธีมพื้นฐานของมันแล้ว",
"restart-to-activate": "Please restart your NodeBB to fully activate this theme" "restart-to-activate": "โปรดรีสตาร์ท NodeBB ของคุณเพื่อเปิดการทำงานของธีมนี้"
} }

View File

@@ -1,18 +1,18 @@
{ {
"you-are-on": "Info - You are on <strong>%1:%2</strong>", "you-are-on": "ข้อมูล - คุณกำลังอยู่บน <strong>%1:%2</strong>",
"nodes-responded": "%1 nodes responded within %2ms!", "nodes-responded": "%1 nodes ตอบสนองแล้วภายใน %2ms!",
"host": "host", "host": "host",
"pid": "pid", "pid": "pid",
"nodejs": "nodejs", "nodejs": "nodejs",
"online": "online", "online": "online",
"git": "git", "git": "git",
"memory": "memory", "memory": "หน่วยความจำ",
"load": "load", "load": "โหลด",
"uptime": "uptime", "uptime": "ระยะเวลาการทำงาน",
"registered": "Registered", "registered": "ลงทะเบียนแล้ว",
"sockets": "Sockets", "sockets": "Sockets",
"guests": "Guests", "guests": "ผู้เยี่ยมเยียน",
"info": "Info" "info": "ข้อมูล"
} }

View File

@@ -1,12 +1,12 @@
{ {
"logger-settings": "Logger Settings", "logger-settings": "การตั้งค่าการบันทึกผลกิจกรรม",
"description": "By enabling the check boxes, you will receive logs to your terminal. If you specify a path, logs will then be saved to a file instead. HTTP logging is useful for collecting statistics about who, when, and what people access on your forum. In addition to logging HTTP requests, we can also log socket.io events. Socket.io logging, in combination with redis-cli monitor, can be very helpful for learning NodeBB's internals.", "description": "ถ้าคุณเลือกช่องนี้, คุณจะได้รับการแสดงผลกิจกรรมทางจอภาพ แต่ถ้าคุณระบุเส้นทางการจัดเก็บผลการบันทึกกิจกรรมจะถูกบันทึกเป็นไฟล์แทน, ผลการบันทึกกิจกรรมของ HTTP มีประโยชน์เพื่อเก็บสถิติเกี่ยวกับ ใคร, เมื่อไหร่ และที่ไหนในฟอรั่มของคุณที่พวกเขาเข้าถึง เช่นเดียวกันกับที่เราสามารถบันทึกผลกิจกรรมอีเวนท์ของ socket.io โดยการบันทึกผลกิจกรรมของ Socket.io นั้นจะบันทึกร่วมกับการจับตาดู redis-cli ซึ่งสามารถช่วยให้เราศึกษา NodeBB จากภายในได้",
"explanation": "Simply check/uncheck the logging settings to enable or disable logging on the fly. No restart needed.", "explanation": "ง่ายมากเพียงแค่ เลือกหรือยกเลิก การตั้งค่าการบันทึกผลกิจกรรม เพื่อเปิดและปิดการบันทึกผลกิจกรรมในทันที ไม่จำเป็นต้องรีสตาร์ท",
"enable-http": "Enable HTTP logging", "enable-http": "เปิดการบันทึกผลกิจกรรมของ HTTP",
"enable-socket": "Enable socket.io event logging", "enable-socket": "เปิดการบันทึกผลกิจกรรมอีเวนท์ของ socket.io",
"file-path": "Path to log file", "file-path": "เส้นทางเพื่อบันทึกไฟล์บันทึกผลกิจกรรม",
"file-path-placeholder": "/path/to/log/file.log ::: leave blank to log to your terminal", "file-path-placeholder": "/path/to/log/file.log ::: ปล่อยว่างถ้าคุณต้องการให้แสดงผลการบันทึกกิจกรรมทางจอภาพ",
"control-panel": "Logger Control Panel", "control-panel": "แผงควบคุมระบบการบันทึกผลกิจกรรม",
"update-settings": "Update Logger Settings" "update-settings": "บันทึกการตั้งค่าการบันทึกผลกิจกรรม"
} }

View File

@@ -1,18 +1,18 @@
{ {
"installed": "Installed", "installed": "ถูกติดตั้งแล้ว",
"active": "Active", "active": "ทำงาน",
"inactive": "Inactive", "inactive": "ไม่ทำงาน",
"out-of-date": "Out of Date", "out-of-date": "รุ่นเก่า",
"none-found": "No plugins found.", "none-found": "ไม่พบปลั๊กอิน",
"none-active": "No Active Plugins", "none-active": "ไม่มีปลั๊กอินที่ทำงาน",
"find-plugins": "Find Plugins", "find-plugins": "ค้นหาปลั๊กอิน",
"plugin-search": "Plugin Search", "plugin-search": "การค้นหาปลั๊กอิน",
"plugin-search-placeholder": "Search for plugin...", "plugin-search-placeholder": "ค้นหาปลั๊กอิน...",
"reorder-plugins": "Re-order Plugins", "reorder-plugins": "เรียงลำดับปลั๊กอินใหม่",
"order-active": "Order Active Plugins", "order-active": "ลำดับการทำงานของปลั๊กอิน",
"dev-interested": "Interested in writing plugins for NodeBB?", "dev-interested": "คุณสนใจที่จะสร้างปลั๊กอินสำหรับ NodeBB หรือไม่?",
"docs-info": "Full documentation regarding plugin authoring can be found in the <a target=\"_blank\" href=\"https://docs.nodebb.org/development/plugins/\">NodeBB Docs Portal</a>.", "docs-info": "เอกสารฉบับเต็มเกี่ยวกับปลั๊กอินสามารถพบได้ที่ <a target=\"_blank\" href=\"https://docs.nodebb.org/development/plugins/\">คลังเอกสาร NodeBB </a>",
"order.description": "Certain plugins work ideally when they are initialised before/after other plugins.", "order.description": "Certain plugins work ideally when they are initialised before/after other plugins.",
"order.explanation": "Plugins load in the order specified here, from top to bottom", "order.explanation": "Plugins load in the order specified here, from top to bottom",

View File

@@ -24,7 +24,7 @@
"keep-updated": "请确保您已及时更新 NodeBB 以获得最新的安全补丁与 Bug 修复。", "keep-updated": "请确保您已及时更新 NodeBB 以获得最新的安全补丁与 Bug 修复。",
"up-to-date": "<p>正在使用 <strong>最新版本</strong> <i class=\"fa fa-check\"></i></p>", "up-to-date": "<p>正在使用 <strong>最新版本</strong> <i class=\"fa fa-check\"></i></p>",
"upgrade-available": "<p>A new version (v%1) has been released. Consider <a href=\"https://docs.nodebb.org/configuring/upgrade/\">upgrading your NodeBB</a>.</p>", "upgrade-available": "<p>A new version (v%1) has been released. Consider <a href=\"https://docs.nodebb.org/configuring/upgrade/\">upgrading your NodeBB</a>.</p>",
"prerelease-upgrade-available": "<p>This is an outdated pre-release version of NodeBB. A new version (v%1) has been released. Consider <a href=\"https://docs.nodebb.org/configuring/upgrade/\">upgrading your NodeBB</a>.</p>", "prerelease-upgrade-available": "<p>你正在使用NodeBB过期的实验版本。新的版本 (v%1) 已经发布。 请考虑<a href=\"https://docs.nodebb.org/en/latest/upgrading/index.html\">更新你的 NodeBB</a></p>",
"prerelease-warning": "<p>正在使用<strong>测试版</strong> NodeBB。可能会出现意外的 Bug。<i class=\"fa fa-exclamation-triangle\"></i></p>", "prerelease-warning": "<p>正在使用<strong>测试版</strong> NodeBB。可能会出现意外的 Bug。<i class=\"fa fa-exclamation-triangle\"></i></p>",
"running-in-development": "<span>论坛正处于开发模式,这可能使其暴露于潜在的危险之中;请联系您的系统管理员。</span>", "running-in-development": "<span>论坛正处于开发模式,这可能使其暴露于潜在的危险之中;请联系您的系统管理员。</span>",

View File

@@ -42,7 +42,7 @@ define('forum/groups/memberlist', ['components', 'forum/infinitescroll'], functi
var $this = $(this); var $this = $(this);
var bottom = ($this[0].scrollHeight - $this.innerHeight()) * 0.9; var bottom = ($this[0].scrollHeight - $this.innerHeight()) * 0.9;
if ($this.scrollTop() > bottom) { if ($this.scrollTop() > bottom && !$('[component="groups/members/search"]').val()) {
loadMoreMembers(); loadMoreMembers();
} }
}); });
@@ -86,7 +86,7 @@ define('forum/groups/memberlist', ['components', 'forum/infinitescroll'], functi
} }
function parseAndTranslate(users, callback) { function parseAndTranslate(users, callback) {
app.parseAndTranslate(templateName, 'members', { app.parseAndTranslate(templateName, 'group.members', {
group: { group: {
members: users, members: users,
isOwner: ajaxify.data.group.isOwner, isOwner: ajaxify.data.group.isOwner,

View File

@@ -85,13 +85,13 @@ helpers.getUserDataByUserSlug = function (userslug, callerUID, callback) {
userData.emailClass = 'hide'; userData.emailClass = 'hide';
if (!(isAdmin || isGlobalModerator || isSelf || (userData.email && userSettings.showemail))) { if (!isAdmin && !isGlobalModerator && !isSelf && (!userSettings.showemail || parseInt(meta.config.hideEmail, 10) === 1)) {
userData.email = ''; userData.email = '';
} else if (!userSettings.showemail) { } else if (!userSettings.showemail) {
userData.emailClass = ''; userData.emailClass = '';
} }
if (!isAdmin && !isGlobalModerator && !isSelf && !userSettings.showfullname) { if (!isAdmin && !isGlobalModerator && !isSelf && (!userSettings.showfullname || parseInt(meta.config.hideFullname, 10) === 1)) {
userData.fullname = ''; userData.fullname = '';
} }

View File

@@ -142,6 +142,9 @@ settingsController.get = function (req, res, callback) {
userData.allowUserHomePage = parseInt(meta.config.allowUserHomePage, 10) === 1; userData.allowUserHomePage = parseInt(meta.config.allowUserHomePage, 10) === 1;
userData.hideFullname = parseInt(meta.config.hideFullname, 10) === 1;
userData.hideEmail = parseInt(meta.config.hideEmail, 10) === 1;
userData.inTopicSearchAvailable = plugins.hasListeners('filter:topic.search'); userData.inTopicSearchAvailable = plugins.hasListeners('filter:topic.search');
userData.title = '[[pages:account/settings]]'; userData.title = '[[pages:account/settings]]';

View File

@@ -91,8 +91,8 @@ userController.getUserDataByUID = function (callerUid, uid, callback) {
return callback(err || new Error('[[error:no-user]]')); return callback(err || new Error('[[error:no-user]]'));
} }
results.userData.email = results.settings.showemail ? results.userData.email : undefined; results.userData.email = results.settings.showemail && parseInt(meta.config.hideEmail, 10) !== 1 ? results.userData.email : undefined;
results.userData.fullname = results.settings.showfullname ? results.userData.fullname : undefined; results.userData.fullname = results.settings.showfullname && parseInt(meta.config.hideFullname, 10) !== 1 ? results.userData.fullname : undefined;
callback(null, results.userData); callback(null, results.userData);
}); });

View File

@@ -39,7 +39,7 @@ usersController.search = function (req, res, next) {
query: req.query.term, query: req.query.term,
searchBy: req.query.searchBy || 'username', searchBy: req.query.searchBy || 'username',
page: req.query.page || 1, page: req.query.page || 1,
sortBy: req.query.sortBy, sortBy: req.query.sortBy || 'joindate',
onlineOnly: req.query.onlineOnly === 'true', onlineOnly: req.query.onlineOnly === 'true',
bannedOnly: req.query.bannedOnly === 'true', bannedOnly: req.query.bannedOnly === 'true',
flaggedOnly: req.query.flaggedOnly === 'true', flaggedOnly: req.query.flaggedOnly === 'true',

View File

@@ -63,29 +63,6 @@ module.exports = function (Groups) {
}; };
Groups.searchMembers = function (data, callback) { Groups.searchMembers = function (data, callback) {
function findUids(query, searchBy, callback) {
query = query.toLowerCase();
async.waterfall([
function (next) {
Groups.getMembers(data.groupName, 0, -1, next);
},
function (members, next) {
user.getUsersFields(members, ['uid'].concat([searchBy]), next);
},
function (users, next) {
var uids = [];
for (var i = 0; i < users.length; i += 1) {
var field = users[i][searchBy];
if (field.toLowerCase().startsWith(query)) {
uids.push(users[i].uid);
}
}
next(null, uids);
},
], callback);
}
if (!data.query) { if (!data.query) {
Groups.getOwnersAndMembers(data.groupName, data.uid, 0, 19, function (err, users) { Groups.getOwnersAndMembers(data.groupName, data.uid, 0, 19, function (err, users) {
callback(err, { users: users }); callback(err, { users: users });
@@ -93,10 +70,10 @@ module.exports = function (Groups) {
return; return;
} }
data.findUids = findUids;
var results; var results;
async.waterfall([ async.waterfall([
function (next) { function (next) {
data.paginate = false;
user.search(data, next); user.search(data, next);
}, },
function (_results, next) { function (_results, next) {
@@ -104,6 +81,16 @@ module.exports = function (Groups) {
var uids = results.users.map(function (user) { var uids = results.users.map(function (user) {
return user && user.uid; return user && user.uid;
}); });
Groups.isMembers(uids, data.groupName, next);
},
function (isMembers, next) {
results.users = results.users.filter(function (user, index) {
return isMembers[index];
});
var uids = results.users.map(function (user) {
return user && user.uid;
});
Groups.ownership.isOwners(uids, data.groupName, next); Groups.ownership.isOwners(uids, data.groupName, next);
}, },
function (isOwners, next) { function (isOwners, next) {

View File

@@ -50,7 +50,7 @@ Tags.parse = function (req, data, meta, link, callback) {
}); });
} }
plugins.fireHook('filter:meta.getMetaTags', { req: req, data: data, defaultTags: defaultTags }, next); plugins.fireHook('filter:meta.getMetaTags', { req: req, data: data, tags: defaultTags }, next);
}, },
links: function (next) { links: function (next) {
var defaultLinks = [{ var defaultLinks = [{
@@ -101,14 +101,14 @@ Tags.parse = function (req, data, meta, link, callback) {
href: nconf.get('relative_path') + '/assets/uploads/system/touchicon-192.png', href: nconf.get('relative_path') + '/assets/uploads/system/touchicon-192.png',
}); });
} }
plugins.fireHook('filter:meta.getLinkTags', { req: req, data: data, defaultLinks: defaultLinks }, next); plugins.fireHook('filter:meta.getLinkTags', { req: req, data: data, links: defaultLinks }, next);
}, },
}, function (err, results) { }, function (err, results) {
if (err) { if (err) {
return callback(err); return callback(err);
} }
meta = results.tags.defaultTags.concat(meta || []).map(function (tag) { meta = results.tags.tags.concat(meta || []).map(function (tag) {
if (!tag || typeof tag.content !== 'string') { if (!tag || typeof tag.content !== 'string') {
winston.warn('Invalid meta tag. ', tag); winston.warn('Invalid meta tag. ', tag);
return tag; return tag;
@@ -139,7 +139,7 @@ Tags.parse = function (req, data, meta, link, callback) {
addIfNotExists(meta, 'property', 'og:image:height', 200); addIfNotExists(meta, 'property', 'og:image:height', 200);
} }
link = results.links.defaultLinks.concat(link || []); link = results.links.links.concat(link || []);
callback(null, { callback(null, {
meta: meta, meta: meta,

View File

@@ -49,6 +49,9 @@ module.exports = function (Posts) {
userData.status = user.getStatus(userData); userData.status = user.getStatus(userData);
userData.signature = validator.escape(String(userData.signature || '')); userData.signature = validator.escape(String(userData.signature || ''));
userData.fullname = validator.escape(String(userData.fullname || '')); userData.fullname = validator.escape(String(userData.fullname || ''));
if (parseInt(meta.config.hideFullname, 10) === 1) {
userData.fullname = undefined;
}
}); });
async.map(userData, function (userData, next) { async.map(userData, function (userData, next) {

View File

@@ -97,6 +97,7 @@ function searchInContent(data, callback) {
function (_metadata, next) { function (_metadata, next) {
metadata = _metadata; metadata = _metadata;
matchCount = metadata.pids.length; matchCount = metadata.pids.length;
if (data.page) { if (data.page) {
var start = Math.max(0, (data.page - 1)) * 10; var start = Math.max(0, (data.page - 1)) * 10;
metadata.pids = metadata.pids.slice(start, start + 10); metadata.pids = metadata.pids.slice(start, start + 10);
@@ -105,7 +106,7 @@ function searchInContent(data, callback) {
posts.getPostSummaryByPids(metadata.pids, data.uid, {}, next); posts.getPostSummaryByPids(metadata.pids, data.uid, {}, next);
}, },
function (posts, next) { function (posts, next) {
// Append metadata from plugin hooks to returned payload (without pids) // Append metadata to returned payload (without pids)
delete metadata.pids; delete metadata.pids;
next(null, Object.assign({ posts: posts, matchCount: matchCount, pageCount: Math.max(1, Math.ceil(parseInt(matchCount, 10) / 10)) }, metadata)); next(null, Object.assign({ posts: posts, matchCount: matchCount, pageCount: Math.max(1, Math.ceil(parseInt(matchCount, 10) / 10)) }, metadata));
}, },

View File

@@ -7,6 +7,7 @@ var db = require('./database');
var posts = require('./posts'); var posts = require('./posts');
var utils = require('./utils'); var utils = require('./utils');
var plugins = require('./plugins'); var plugins = require('./plugins');
var meta = require('./meta');
var user = require('./user'); var user = require('./user');
var categories = require('./categories'); var categories = require('./categories');
var privileges = require('./privileges'); var privileges = require('./privileges');
@@ -135,6 +136,12 @@ Topics.getTopicsByTids = function (tids, uid, callback) {
}, next); }, next);
}, },
function (results, next) { function (results, next) {
if (parseInt(meta.config.hideFullname, 10) === 1) {
results.users.forEach(function (user) {
user.fullname = undefined;
});
}
var users = _.zipObject(uids, results.users); var users = _.zipObject(uids, results.users);
var categories = _.zipObject(cids, results.categories); var categories = _.zipObject(cids, results.categories);

View File

@@ -177,7 +177,7 @@ module.exports = function (User) {
async.parallel([ async.parallel([
function (next) { function (next) {
getIPMatchedUsers(user.ip, next); getIPMatchedUsers(user, next);
}, },
function (next) { function (next) {
getSpamData(user, next); getSpamData(user, next);
@@ -196,14 +196,18 @@ module.exports = function (User) {
], callback); ], callback);
}; };
function getIPMatchedUsers(ip, callback) { function getIPMatchedUsers(user, callback) {
async.waterfall([ async.waterfall([
function (next) { function (next) {
User.getUidsFromSet('ip:' + ip + ':uid', 0, -1, next); User.getUidsFromSet('ip:' + user.ip + ':uid', 0, -1, next);
}, },
function (uids, next) { function (uids, next) {
User.getUsersFields(uids, ['uid', 'username', 'picture'], next); User.getUsersFields(uids, ['uid', 'username', 'picture'], next);
}, },
function (data, next) {
user.ipMatch = data;
next();
},
], callback); ], callback);
} }

View File

@@ -23,11 +23,8 @@ module.exports = function (User) {
var searchResult = {}; var searchResult = {};
async.waterfall([ async.waterfall([
function (next) { function (next) {
if (data.findUids) { var searchMethod = data.findUids || findUids;
data.findUids(query, searchBy, next); searchMethod(query, searchBy, data.hardCap, next);
} else {
findUids(query, searchBy, next);
}
}, },
function (uids, next) { function (uids, next) {
filterAndSortUids(uids, data, next); filterAndSortUids(uids, data, next);
@@ -57,7 +54,7 @@ module.exports = function (User) {
], callback); ], callback);
}; };
function findUids(query, searchBy, callback) { function findUids(query, searchBy, hardCap, callback) {
if (!query) { if (!query) {
return callback(null, []); return callback(null, []);
} }
@@ -66,7 +63,7 @@ module.exports = function (User) {
var max = query.substr(0, query.length - 1) + String.fromCharCode(query.charCodeAt(query.length - 1) + 1); var max = query.substr(0, query.length - 1) + String.fromCharCode(query.charCodeAt(query.length - 1) + 1);
var resultsPerPage = parseInt(meta.config.userSearchResultsPerPage, 10) || 20; var resultsPerPage = parseInt(meta.config.userSearchResultsPerPage, 10) || 20;
var hardCap = resultsPerPage * 10; hardCap = hardCap || resultsPerPage * 10;
async.waterfall([ async.waterfall([
function (next) { function (next) {
@@ -82,9 +79,11 @@ module.exports = function (User) {
} }
function filterAndSortUids(uids, data, callback) { function filterAndSortUids(uids, data, callback) {
var sortBy = data.sortBy || 'joindate'; var fields = [];
var fields = ['uid', sortBy]; if (data.sortBy) {
fields.push(data.sortBy);
}
if (data.onlineOnly) { if (data.onlineOnly) {
fields = fields.concat(['status', 'lastonline']); fields = fields.concat(['status', 'lastonline']);
} }
@@ -95,6 +94,12 @@ module.exports = function (User) {
fields.push('flags'); fields.push('flags');
} }
if (!fields.length) {
return callback(null, uids);
}
fields = ['uid'].concat(fields);
async.waterfall([ async.waterfall([
function (next) { function (next) {
User.getUsersFields(uids, fields, next); User.getUsersFields(uids, fields, next);
@@ -118,7 +123,9 @@ module.exports = function (User) {
}); });
} }
sortUsers(userData, sortBy); if (data.sortBy) {
sortUsers(userData, data.sortBy);
}
uids = userData.map(function (user) { uids = userData.map(function (user) {
return user && user.uid; return user && user.uid;

View File

@@ -71,6 +71,18 @@
<span class="mdl-switch__label"><strong>[[admin/settings/user:user-info-private]]</strong></span> <span class="mdl-switch__label"><strong>[[admin/settings/user:user-info-private]]</strong></span>
</label> </label>
</div> </div>
<div class="checkbox">
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
<input class="mdl-switch__input" type="checkbox" data-field="hideFullname">
<span class="mdl-switch__label"><strong>[[admin/settings/user:hide-fullname]]</strong></span>
</label>
</div>
<div class="checkbox">
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
<input class="mdl-switch__input" type="checkbox" data-field="hideEmail">
<span class="mdl-switch__label"><strong>[[admin/settings/user:hide-email]]</strong></span>
</label>
</div>
</form> </form>
</div> </div>
</div> </div>

View File

@@ -1534,4 +1534,54 @@ describe('User', function () {
}); });
}); });
}); });
describe('hideEmail/hideFullname', function () {
var uid;
after(function (done) {
meta.config.hideEmail = 0;
meta.config.hideFullname = 0;
done();
});
it('should hide email and fullname', function (done) {
meta.config.hideEmail = 1;
meta.config.hideFullname = 1;
User.create({
username: 'hiddenemail',
email: 'should@be.hidden',
fullname: 'baris soner usakli',
}, function (err, _uid) {
uid = _uid;
assert.ifError(err);
request(nconf.get('url') + '/api/user/hiddenemail', { json: true }, function (err, res, body) {
assert.ifError(err);
assert.equal(body.fullname, '');
assert.equal(body.email, '');
done();
});
});
});
it('should hide fullname in topic list and topic', function (done) {
Topics.post({
uid: uid,
title: 'Topic hidden',
content: 'lorem ipsum',
cid: testCid,
}, function (err) {
assert.ifError(err);
request(nconf.get('url') + '/api/recent', { json: true }, function (err, res, body) {
assert.ifError(err);
assert(!body.topics[0].user.hasOwnProperty('fullname'));
request(nconf.get('url') + '/api/topic/' + body.topics[0].slug, { json: true }, function (err, res, body) {
assert.ifError(err);
assert(!body.posts[0].user.hasOwnProperty('fullname'));
done();
});
});
});
});
});
}); });