mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-01-22 07:23:01 +01:00
breaking: refactor topic events
for proper i18n support both `user locked this topic 3 hours ago` & `user locked this topic on 19 Oct 2022, 11:42`
This commit is contained in:
@@ -100,8 +100,8 @@
|
||||
"nodebb-plugin-spam-be-gone": "2.0.4",
|
||||
"nodebb-rewards-essentials": "0.2.1",
|
||||
"nodebb-theme-lavender": "7.0.2",
|
||||
"nodebb-theme-peace": "2.0.8",
|
||||
"nodebb-theme-persona": "13.0.28",
|
||||
"nodebb-theme-peace": "2.0.9",
|
||||
"nodebb-theme-persona": "13.0.30",
|
||||
"nodebb-widget-essentials": "7.0.2",
|
||||
"nodemailer": "6.8.0",
|
||||
"nprogress": "0.2.0",
|
||||
|
||||
@@ -43,16 +43,26 @@
|
||||
"ban-ip": "Ban IP",
|
||||
"view-history": "Edit History",
|
||||
|
||||
"locked-by": "Locked by",
|
||||
"unlocked-by": "Unlocked by",
|
||||
"pinned-by": "Pinned by",
|
||||
"unpinned-by": "Unpinned by",
|
||||
"deleted-by": "Deleted by",
|
||||
"restored-by": "Restored by",
|
||||
"moved-from-by": "Moved from %1 by",
|
||||
"queued-by": "Post queued for approval →",
|
||||
"backlink": "Referenced by",
|
||||
"forked-by": "Forked by",
|
||||
"user-locked-topic-ago": "%1 locked this topic %2",
|
||||
"user-locked-topic-on": "%1 locked this topic on %2",
|
||||
"user-unlocked-topic-ago": "%1 unlocked this topic %2",
|
||||
"user-unlocked-topic-on": "%1 unlocked this topic on %2",
|
||||
"user-pinned-topic-ago": "%1 pinned this topic %2",
|
||||
"user-pinned-topic-on": "%1 pinned this topic on %2",
|
||||
"user-unpinned-topic-ago": "%1 unpinned this topic %2",
|
||||
"user-unpinned-topic-on": "%1 unpinned this topic on %2",
|
||||
"user-deleted-topic-ago": "%1 deleted this topic %2",
|
||||
"user-deleted-topic-on": "%1 deleted this topic on %2",
|
||||
"user-restored-topic-ago": "%1 restored this topic %2",
|
||||
"user-restored-topic-on": "%1 restored this topic on %2",
|
||||
"user-moved-topic-from-ago": "%1 moved this topic from %2 %3",
|
||||
"user-moved-topic-from-on": "%1 moved this topic from %2 on %3",
|
||||
"user-queued-post-ago": "%1 <a href=\"%2\">queued</a> post for approval %3",
|
||||
"user-queued-post-on": "%1 <a href=\"%2\">queued</a> post for approval on %3",
|
||||
"user-referenced-topic-ago": "%1 <a href=\"%2\">referenced</a> this topic %3",
|
||||
"user-referenced-topic-on": "%1 <a href=\"%2\">referenced</a> this topic on %3",
|
||||
"user-forked-topic-ago": "%1 <a href=\"%2\">forked</a> this topic %3",
|
||||
"user-forked-topic-on": "%1 <a href=\"%2\">forked</a> this topic on %3",
|
||||
|
||||
"bookmark_instructions" : "Click here to return to the last read post in this thread.",
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const _ = require('lodash');
|
||||
const nconf = require('nconf');
|
||||
const db = require('../database');
|
||||
const meta = require('../meta');
|
||||
const user = require('../user');
|
||||
@@ -9,6 +10,10 @@ const categories = require('../categories');
|
||||
const plugins = require('../plugins');
|
||||
const translator = require('../translator');
|
||||
const privileges = require('../privileges');
|
||||
const utils = require('../utils');
|
||||
const helpers = require('../helpers');
|
||||
|
||||
const relative_path = nconf.get('relative_path');
|
||||
|
||||
const Events = module.exports;
|
||||
|
||||
@@ -20,49 +25,49 @@ const Events = module.exports;
|
||||
* You can then log a custom topic event by calling `topics.events.log(tid, { type, uid });`
|
||||
* `uid` is optional; if you pass in a valid uid in the payload,
|
||||
* the user avatar/username will be rendered as part of the event text
|
||||
*
|
||||
* see https://github.com/NodeBB/nodebb-plugin-question-and-answer/blob/master/library.js#L288-L306
|
||||
*/
|
||||
Events._types = {
|
||||
pin: {
|
||||
icon: 'fa-thumb-tack',
|
||||
text: '[[topic:pinned-by]]',
|
||||
translation: async event => translateSimple(event, 'topic:user-pinned-topic'),
|
||||
},
|
||||
unpin: {
|
||||
icon: 'fa-thumb-tack fa-rotate-90',
|
||||
text: '[[topic:unpinned-by]]',
|
||||
translation: async event => translateSimple(event, 'topic:user-unpinned-topic'),
|
||||
},
|
||||
lock: {
|
||||
icon: 'fa-lock',
|
||||
text: '[[topic:locked-by]]',
|
||||
translation: async event => translateSimple(event, 'topic:user-locked-topic'),
|
||||
},
|
||||
unlock: {
|
||||
icon: 'fa-unlock',
|
||||
text: '[[topic:unlocked-by]]',
|
||||
translation: async event => translateSimple(event, 'topic:user-unlocked-topic'),
|
||||
},
|
||||
delete: {
|
||||
icon: 'fa-trash',
|
||||
text: '[[topic:deleted-by]]',
|
||||
translation: async event => translateSimple(event, 'topic:user-deleted-topic'),
|
||||
},
|
||||
restore: {
|
||||
icon: 'fa-trash-o',
|
||||
text: '[[topic:restored-by]]',
|
||||
translation: async event => translateSimple(event, 'topic:user-restored-topic'),
|
||||
},
|
||||
move: {
|
||||
icon: 'fa-arrow-circle-right',
|
||||
// text: '[[topic:moved-from-by]]',
|
||||
translation: async event => translateEventArgs(event, 'topic:user-moved-topic-from', renderUser(event), `${event.fromCategory.name}`, renderTimeago(event)),
|
||||
},
|
||||
'post-queue': {
|
||||
icon: 'fa-history',
|
||||
text: '[[topic:queued-by]]',
|
||||
href: '/post-queue',
|
||||
translation: async event => translateEventArgs(event, 'topic:user-queued-post', renderUser(event), `/post-queue`, renderTimeago(event)),
|
||||
},
|
||||
backlink: {
|
||||
icon: 'fa-link',
|
||||
text: '[[topic:backlink]]',
|
||||
translation: async event => translateEventArgs(event, 'topic:user-referenced-topic', renderUser(event), `${relative_path}${event.href}`, renderTimeago(event)),
|
||||
},
|
||||
fork: {
|
||||
icon: 'fa-code-fork',
|
||||
text: '[[topic:forked-by]]',
|
||||
translation: async event => translateEventArgs(event, 'topic:user-forked-topic', renderUser(event), `${relative_path}${event.href}`, renderTimeago(event)),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -72,6 +77,40 @@ Events.init = async () => {
|
||||
Events._types = types;
|
||||
};
|
||||
|
||||
async function translateEventArgs(event, prefix, ...args) {
|
||||
const key = getTranslationKey(event, prefix);
|
||||
const compiled = translator.compile.apply(null, [key, ...args]);
|
||||
return utils.decodeHTMLEntities(await translator.translate(compiled));
|
||||
}
|
||||
|
||||
async function translateSimple(event, prefix) {
|
||||
return await translateEventArgs(event, prefix, renderUser(event), renderTimeago(event));
|
||||
}
|
||||
|
||||
Events.translateSimple = translateSimple; // so plugins can perform translate
|
||||
Events.translateEventArgs = translateEventArgs; // so plugins can perform translate
|
||||
|
||||
// generate `user-locked-topic-ago` or `user-locked-topic-on` based on timeago cutoff setting
|
||||
function getTranslationKey(event, prefix) {
|
||||
const cutoffMs = 1000 * 60 * 60 * 24 * Math.max(0, parseInt(meta.config.timeagoCutoff, 10));
|
||||
let translationSuffix = 'ago';
|
||||
if (cutoffMs > 0 && Date.now() - event.timestamp > cutoffMs) {
|
||||
translationSuffix = 'on';
|
||||
}
|
||||
return `${prefix}-${translationSuffix}`;
|
||||
}
|
||||
|
||||
function renderUser(event) {
|
||||
if (!event.user || event.user.system) {
|
||||
return '[[global:system-user]]';
|
||||
}
|
||||
return `<a href="${relative_path}/user/${event.user.userslug}">${helpers.buildAvatar(event.user, '16px', true)} ${event.user.username}</a>`;
|
||||
}
|
||||
|
||||
function renderTimeago(event) {
|
||||
return `<span class="timeago timeline-text" title="${event.timestampISO}"></span>`;
|
||||
}
|
||||
|
||||
Events.get = async (tid, uid, reverse = false) => {
|
||||
const topics = require('.');
|
||||
|
||||
@@ -154,12 +193,17 @@ async function modifyEvent({ tid, uid, eventIds, timestamps, events }) {
|
||||
}
|
||||
if (event.hasOwnProperty('fromCid')) {
|
||||
event.fromCategory = fromCategories[event.fromCid];
|
||||
event.text = translator.compile('topic:moved-from-by', event.fromCategory.name);
|
||||
}
|
||||
|
||||
Object.assign(event, Events._types[event.type]);
|
||||
});
|
||||
|
||||
await Promise.all(events.map(async (event) => {
|
||||
if (Events._types[event.type].translation) {
|
||||
event.text = await Events._types[event.type].translation(event);
|
||||
}
|
||||
}));
|
||||
|
||||
// Sort events
|
||||
events.sort((a, b) => a.timestamp - b.timestamp);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user