LLWiki正在建设中,欢迎加入我们!
MediaWiki:Gadget-CommentsInLocalTime.js
跳转到导航
跳转到搜索
注意:在保存之后,您可能需要清除浏览器缓存才能看到所作出的变更的影响。
- Firefox或Safari:按住Shift的同时单击刷新,或按Ctrl-F5或Ctrl-R(Mac为⌘-R)
- Google Chrome:按Ctrl-Shift-R(Mac为⌘-Shift-R)
- Internet Explorer:按住Ctrl的同时单击刷新,或按Ctrl-F5
- Opera:前往菜单 → 设置(Mac为Opera → Preferences),然后隐私和安全 → 清除浏览数据 → 缓存的图片和文件。
//<nowiki> // 由ResourceLoader直接调用,不可使用ES6语法 /** * @Function: 将签名的时间戳替换为本地时区,用户可以自定义时间格式,但需要一定的知识和技术 * @Dependencies: mediawiki.jqueryMsg(用于英文时间格式), moment, ext.gadget.SettingsDialog * @Source: [[moegirl:User:AnnAngela/js/CommentsInLocalTime.js]] * @OriginalVersion: [[wikipedia:User:Mxn/CommentsInLocalTime.js]] * @Author: [[wikipedia:User:Mxn]] * @EditedBy: [[moegirl:User:AnnAngela]]、[[User:Bhsd]] */ "use strict"; /* global moment, OO, wgULS, wgUCS */ const ns = mw.config.get( 'wgNamespaceNumber' ), pagename = mw.config.get( 'wgPageName' ), action = mw.config.get('wgAction'); if ((ns >= 0 && ns % 2 == 1 || pagename == "Help:互助客棧") && ['view', 'submit', 'edit'].includes(action)) { // 1. 更新设置 mw.gadgets.CommentsInLocalTime = $.extend(true, {locale: moment.locale()}, mw.storage.getObject( 'gadget-CommentsInLocalTime' ), mw.gadgets.CommentsInLocalTime); const settings = mw.gadgets.CommentsInLocalTime, lang = settings.lang, // 注意这是一个数组!提供一套默认的英文设置 isEn = lang == 'en', // lang会先自动转化为字符串再比较 date = isEn ? 'ddd, ll' : settings.date, time = isEn ? 'LT' : settings.time, locale = isEn ? 'en' : settings.locale, i18n = settings.i18n || {}, offset = settings.utcoffset; var tz = settings.timezone; // 2. 设置本地化消息 mw.messages.set( $.extend( wgULS({ // 这些消息用于小工具设置 'gadget-lc-label': '以本地时区显示签名时间戳', 'gadget-lc-time': '时间格式', 'gadget-lc-help': '请参考$1文档。', 'gadget-lc-lang': '使用预定义的时间格式', 'gadget-lc-en': '英语格式', 'gadget-lc-locale': '语言', 'gadget-lc-plural': '英语单复数请使用PLURAL魔术字,如$1。', 'gadget-lc-tz': '显示时区', 'gadget-lc-tzhelp': '请使用IANA时区名称。', 'gadget-lc-tzerror': '错误的时区名称!当前显示为本地时区。', 'gadget-lc-offsetHelp': '优先级低于时区名称。', 'gadget-lc-tzerror-offset': '错误的时区名称!改为由UTC偏移量设置时区。' }, { 'gadget-lc-label': '以本地時區顯示簽名時間戳', 'gadget-lc-time': '時間格式', 'gadget-lc-help': '請參考$1文檔。', 'gadget-lc-lang': '使用預定義的時間格式', 'gadget-lc-en': '英語格式', 'gadget-lc-locale': '語言', 'gadget-lc-plural': '英語單複數請使用PLURAL魔術字,如$1。', 'gadget-lc-tz': '顯示時區', 'gadget-lc-tzhelp': '請使用IANA時區名稱。', 'gadget-lc-tzerror': '錯誤的時區名稱!當前顯示為本地時區。', 'gadget-lc-offsetHelp': '優先級低於時區名稱。', 'gadget-lc-tzerror-offset': '錯誤的時區名稱!改為由UTC偏移量設置時區。' }), wgUCS( // 这些消息用于页面内容 {'gadget-lc-error': '错误的签名时间!', 'gadget-lc-m': '$1个月前', 'gadget-lc-tip': "原始时间戳:"}, {'gadget-lc-error': '錯誤的簽名時間!', 'gadget-lc-m': '$1個月前', 'gadget-lc-tip': "原始時間戳:"} ), { 'gadget-lc-offset': 'UTC偏移量', 'gadget-lc-date': '日期格式', 'gadget-lc-y': '$1年前', 'gadget-lc-d': "$1天前", 'gadget-lc-today': '今天', 'gadget-lc-yesterday': '昨天', 'gadget-lc-i18n': '本地化文字消息', 'gadget-lc-yy': '若干年前', 'gadget-lc-mm': '若干月前', 'gadget-lc-dd': '若干天前', 'gadget-lc-td': '今天', 'gadget-lc-yd': '昨天' }, isEn ? { 'gadget-lc-today': 'Today', 'gadget-lc-yesterday': 'Yesterday', 'gadget-lc-y': '$1 year{{PLURAL:$1||s}} ago', 'gadget-lc-m': '$1 month{{PLURAL:$1||s}} ago', 'gadget-lc-d': '$1 day{{PLURAL:$1||s}} ago' } : i18n) ); // 3. 检查时区 try { Intl.DateTimeFormat('en-us', {timeZone: tz}); } catch (error) { tz = undefined; mw.notify( mw.msg('gadget-lc-tzerror' + (offset ? '-offset' : '')), {type: 'error'} ); } // 4. 小工具设置 const helpInfo = new OO.ui.HtmlSnippet( mw.msg('gadget-lc-help', $('<a>', { target: "_blank", text: 'moment.js', rel: 'noreferrer noopener', href: "//momentjscom.readthedocs.io/en/latest/moment/04-displaying/01-format/" }).prop( 'outerHTML' )) ), helpPlural = new OO.ui.HtmlSnippet( mw.msg('gadget-lc-plural', '<br><code>{{PLURAL:$1|day|days}}</code>') ), locales = moment.locales(); mw.settingsDialog.addTab({name: 'CommentsInLocalTime', label: 'gadget-lc-label', items: [ {key: 'timezone', type: 'Text', label: 'gadget-lc-tz', help: mw.msg('gadget-lc-tzhelp'), config: {value: tz}}, {key: 'utcoffset', type: 'Number', label: 'gadget-lc-offset', help: mw.msg('gadget-lc-offsetHelp'), config: {max: 14, min: -12, step: 0.5, buttonStep: 1, inputFilter: function(num) { return num.replace('+', ''); }} }, {key: 'lang', type: 'CheckboxMultiselect', label: 'gadget-lc-lang', config: {options: [{data: 'en', label: mw.msg('gadget-lc-en')}]} }, {key: 'locale', type: 'Dropdown', label: 'gadget-lc-locale', config: { options: locales.map(function(ele) { return {data: ele}; }), disabled: isEn, inputFilter: function(locale) { return locales.includes( locale ) ? locale : moment.locale(); }} }, {key: 'date', type: 'Text', label: 'gadget-lc-date', help: helpInfo, config: {disabled: isEn}}, {key: 'time', type: 'Text', label: 'gadget-lc-time', help: helpInfo, config: {disabled: isEn}} ], fields: [{key: 'i18n', label: 'gadget-lc-i18n', items: [ {key: 'gadget-lc-y', type: 'Text', label: 'gadget-lc-yy', help: helpPlural, config: {disabled: isEn, validate: /^[^[]*$/} }, {key: 'gadget-lc-m', type: 'Text', label: 'gadget-lc-mm', help: helpPlural, config: {disabled: isEn, validate: /^[^[]*$/} }, {key: 'gadget-lc-d', type: 'Text', label: 'gadget-lc-dd', help: helpPlural, config: {disabled: isEn, validate: /^[^[]*$/} }, {key: 'gadget-lc-today', type: 'Text', label: 'gadget-lc-td', config: {disabled: isEn, validate: /^[^[]*$/} }, {key: 'gadget-lc-yesterday', type: 'Text', label: 'gadget-lc-yd', config: {disabled: isEn, validate: /^[^[]*$/} } ]}], help: '以本地时区显示签名时间戳'}); mw.hook( 'settings.dialog' ).add(function(params) { if (params.name != 'CommentsInLocalTime') { return; } console.log('Hook: settings.dialog, 开始调整小工具设置 - CommentsInLocalTime'); const items = params.items, i = items.findIndex(function(ele) { return ele.key == 'lang'; }); items[i].widget.on('change', function(value) { // 使用英语的设置组合 const disabled = value.length; items.slice(i + 1).forEach(function(ele) { ele.widget.setDisabled( disabled ); }); params.fields[0].items.forEach(function(ele) { ele.widget.setDisabled( disabled ); }); }); }); // 5. 主体程序:替代签名时间戳。合法的签名时间戳必须以CST为时区。 const regExp = /^\d{4}年\d{1,2}月\d{1,2}日\s*(?:[((]?(?:星期)?[一二三四五六日][))]?)?\s*(\d\d:\d\d)?\s*[((]CST[))]$/, weekdays = ['日', '一', '二', '三', '四', '五', '六'], // 用户可以自定义日期格式,否则模拟中文格式(用户可能未安装) formatDate = function(then) { // 附带左半中括号[ return '[' + then.format(date || 'YYYY年M月D日 星期' + weekdays[ then.day() ]); }, fromNow = function(then, now) { // 附带右半中括号] const y = now.diff(then, 'year'), m = y ? null : now.diff(then, 'month'), d = y || m ? null : now.diff(then, 'day'); return ' (' + (y ? mw.msg('gadget-lc-y', y) : m ? mw.msg('gadget-lc-m', m) : mw.msg('gadget-lc-d', d)) + ')]'; }, display = function(then, withTime, now) { // 不使用moment.js自带的模糊时间方法fromNow const thenTz = mw.convertTimezone(then, tz || offset); return then.calendar(null, { sameDay: '[' + mw.msg('gadget-lc-today') + ']', lastDay: '[' + mw.msg('gadget-lc-yesterday') + ']', lastWeek: formatDate(thenTz[0]) + fromNow(then, now), sameElse: formatDate(thenTz[0]) + fromNow(then, now) }) + (withTime ? ' ' + thenTz[0].format(time || 'HH:mm') : '') + ' (' + thenTz[1] + ')'; }; mw.hook( 'wikipage.content' ).add(function($content) { const now = moment(), // 固定以页面内容生成的时间作为“当前”时点 $comments = $content.find( 'time' ).filter(function() { return regExp.test( this.textContent ); // 合法的时间戳总是time标签 }); if ($comments.length === 0) { return; } console.log('Hook: wikipage.content,开始替换签名时间戳'); $comments.each(function() { const string = this.textContent, then = moment(string + '00:00+08', 'YYYY-MM-DD HH:mm Z').locale(locale), // 00:00是未输入时间时的默认值 isValid = then.isValid() && now.isAfter( then ); // 无效的输入并不会让moment抛出错误,只会警告 $(this).addClass('LocalComments' + (isValid ? '' : ' error')) .data('title', mw.msg('gadget-lc-tip') + string) .text(isValid ? display(then, string[1], now) : mw.msg( 'gadget-lc-error' )) .data('time', isValid ? then : undefined); // 保存一份moment对象以供未来调用 }); mw.hook( 'local.comments' ).fire( $content ); }); mw.tipsy('#bodyContent', '.LocalComments', {anchor: false}); // 尽量采取delegate的形式处理交互事件 } //</nowiki> // [[category:作为模块的小工具]] [[category:讨论工具]] [[category:桌面版小工具]] [[category:手机版小工具]] // {{DEFAULTSORT:CommentsInLocalTime.js}}