@waline/vercel 1.37.0 → 1.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -1
- package/src/config/config.js +7 -2
- package/src/controller/comment/rss.js +158 -0
- package/src/controller/token.js +3 -1
- package/src/controller/user.js +21 -0
- package/src/locales/de.json +19 -0
- package/src/locales/es.json +19 -0
- package/src/locales/fr.json +19 -0
- package/src/locales/index.js +21 -2
- package/src/locales/jp.json +19 -0
- package/src/locales/ko-KR.json +19 -0
- package/src/locales/pt-BR.json +19 -0
- package/src/locales/ru.json +19 -0
- package/src/locales/vi-VN.json +19 -0
- package/src/logic/base.js +1 -1
- package/src/logic/comment/rss.js +54 -0
- package/src/logic/user.js +25 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@waline/vercel",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.39.0",
|
|
4
4
|
"description": "vercel server for waline comment system",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"blog",
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"nunjucks": "^3.2.4",
|
|
44
44
|
"phpass": "^0.1.1",
|
|
45
45
|
"prismjs": "^1.30.0",
|
|
46
|
+
"rss": "^1.2.2",
|
|
46
47
|
"speakeasy": "^2.0.0",
|
|
47
48
|
"think-helper": "^1.1.4",
|
|
48
49
|
"think-logger3": "^1.4.0",
|
package/src/config/config.js
CHANGED
|
@@ -48,11 +48,12 @@ const {
|
|
|
48
48
|
COMMENT_AUDIT,
|
|
49
49
|
} = process.env;
|
|
50
50
|
|
|
51
|
-
let storage =
|
|
52
|
-
let jwtKey = JWT_TOKEN
|
|
51
|
+
let storage = null;
|
|
52
|
+
let jwtKey = JWT_TOKEN;
|
|
53
53
|
|
|
54
54
|
if (LEAN_KEY) {
|
|
55
55
|
storage = 'leancloud';
|
|
56
|
+
jwtKey = jwtKey || LEAN_KEY;
|
|
56
57
|
} else if (MONGO_DB) {
|
|
57
58
|
storage = 'mongodb';
|
|
58
59
|
jwtKey = jwtKey || MONGO_PASSWORD;
|
|
@@ -75,6 +76,10 @@ if (LEAN_KEY) {
|
|
|
75
76
|
jwtKey = jwtKey || TENCENTCLOUD_SECRETKEY || TCB_KEY || TCB_ENV;
|
|
76
77
|
}
|
|
77
78
|
|
|
79
|
+
if (storage === null) {
|
|
80
|
+
throw new Error('No valid storage found. Please check your environment variables.');
|
|
81
|
+
}
|
|
82
|
+
|
|
78
83
|
if (think.env === 'cloudbase' && storage === 'sqlite') {
|
|
79
84
|
throw new Error("You can't use SQLite in CloudBase platform.");
|
|
80
85
|
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
const RSS = require('rss');
|
|
2
|
+
const BaseRest = require('../rest.js');
|
|
3
|
+
const { getMarkdownParser } = require('../../service/markdown/index.js');
|
|
4
|
+
|
|
5
|
+
const markdownParser = getMarkdownParser();
|
|
6
|
+
|
|
7
|
+
const isHttpUrl = (value) => /^(https?:)?\/\//i.test(value);
|
|
8
|
+
|
|
9
|
+
const buildAbsoluteUrl = (baseUrl, path) => {
|
|
10
|
+
if (!path) return baseUrl || '';
|
|
11
|
+
if (isHttpUrl(path)) return path;
|
|
12
|
+
if (!baseUrl) return path;
|
|
13
|
+
const normalizedBase = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
|
|
14
|
+
const normalizedPath = path.startsWith('/') ? path : `/${path}`;
|
|
15
|
+
|
|
16
|
+
return `${normalizedBase}${normalizedPath}`;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const buildRssXml = ({ title, link, description, items }) => {
|
|
20
|
+
const channelLink = link || '';
|
|
21
|
+
const now = new Date().toUTCString();
|
|
22
|
+
|
|
23
|
+
const feed = new RSS({
|
|
24
|
+
title,
|
|
25
|
+
description,
|
|
26
|
+
site_url: channelLink,
|
|
27
|
+
pubDate: now,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
items.forEach((item) => {
|
|
31
|
+
feed.item({
|
|
32
|
+
title: item.title || 'Comment',
|
|
33
|
+
description: item.description,
|
|
34
|
+
url: item.link || '',
|
|
35
|
+
guid: item.guid || item.link || '',
|
|
36
|
+
date: item.pubDate || now,
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
return feed.xml({ indent: true });
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const setRssResponse = (ctx, xml) => {
|
|
44
|
+
ctx.set('Content-Type', 'application/rss+xml; charset=utf-8');
|
|
45
|
+
ctx.body = xml;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
module.exports = class extends BaseRest {
|
|
49
|
+
constructor(ctx) {
|
|
50
|
+
super(ctx);
|
|
51
|
+
this.modelInstance = this.getModel('Comment');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async getAction() {
|
|
55
|
+
const { path, email, user_id: userId, count } = this.get();
|
|
56
|
+
const limit = Number.isFinite(Number(count)) ? Number(count) : 20;
|
|
57
|
+
const safeLimit = Math.min(Math.max(limit, 1), 50);
|
|
58
|
+
|
|
59
|
+
const siteUrl = process.env.SITE_URL || this.ctx.serverURL;
|
|
60
|
+
const siteName = process.env.SITE_NAME || 'Waline';
|
|
61
|
+
|
|
62
|
+
const where = {
|
|
63
|
+
status: ['NOT IN', ['waiting', 'spam']],
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
if (path) {
|
|
67
|
+
where.url = path;
|
|
68
|
+
} else if (email || userId) {
|
|
69
|
+
const parentWhere = {
|
|
70
|
+
status: ['NOT IN', ['waiting', 'spam']],
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
if (email && userId) {
|
|
74
|
+
parentWhere._complex = {
|
|
75
|
+
_logic: 'or',
|
|
76
|
+
mail: email,
|
|
77
|
+
user_id: userId,
|
|
78
|
+
};
|
|
79
|
+
} else if (email) {
|
|
80
|
+
parentWhere.mail = email;
|
|
81
|
+
} else if (userId) {
|
|
82
|
+
parentWhere.user_id = userId;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const parents = await this.modelInstance.select(parentWhere, {});
|
|
86
|
+
const parentIds = parents.map(({ objectId }) => objectId).filter(Boolean);
|
|
87
|
+
|
|
88
|
+
if (parentIds.length === 0) {
|
|
89
|
+
setRssResponse(
|
|
90
|
+
this.ctx,
|
|
91
|
+
buildRssXml({
|
|
92
|
+
title: `${siteName} Reply Comments`,
|
|
93
|
+
link: siteUrl,
|
|
94
|
+
description: 'Recent reply comments.',
|
|
95
|
+
items: [],
|
|
96
|
+
}),
|
|
97
|
+
);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
where.pid = ['IN', parentIds];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const comments = await this.modelInstance.select(where, {
|
|
105
|
+
desc: 'insertedAt',
|
|
106
|
+
limit: safeLimit,
|
|
107
|
+
field: ['comment', 'insertedAt', 'link', 'nick', 'url', 'user_id'],
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const userModel = this.getModel('Users');
|
|
111
|
+
const userIds = [...new Set(comments.map(({ user_id }) => user_id).filter(Boolean))];
|
|
112
|
+
let users = [];
|
|
113
|
+
|
|
114
|
+
if (userIds.length > 0) {
|
|
115
|
+
users = await userModel.select(
|
|
116
|
+
{ objectId: ['IN', userIds] },
|
|
117
|
+
{ field: ['display_name', 'url'] },
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const items = comments.map((comment) => {
|
|
122
|
+
const user = users.find(({ objectId }) => objectId === comment.user_id);
|
|
123
|
+
const nick = user?.display_name || comment.nick || 'Anonymous';
|
|
124
|
+
const commentUrl = buildAbsoluteUrl(siteUrl, comment.url);
|
|
125
|
+
const itemLink = commentUrl ? `${commentUrl}#${comment.objectId}` : '';
|
|
126
|
+
const description = markdownParser(comment.comment || '');
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
title: `${nick} commented${comment.url ? ` on ${comment.url}` : ''}`,
|
|
130
|
+
link: itemLink || commentUrl,
|
|
131
|
+
guid: comment.objectId,
|
|
132
|
+
pubDate: new Date(comment.insertedAt).toUTCString(),
|
|
133
|
+
description,
|
|
134
|
+
};
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
const title = path
|
|
138
|
+
? `${siteName} Comments for ${path}`
|
|
139
|
+
: email || userId
|
|
140
|
+
? `${siteName} Reply Comments`
|
|
141
|
+
: `${siteName} Recent Comments`;
|
|
142
|
+
const description = path
|
|
143
|
+
? `Recent comments for ${path}.`
|
|
144
|
+
: email || userId
|
|
145
|
+
? 'Recent reply comments.'
|
|
146
|
+
: 'Recent comments.';
|
|
147
|
+
|
|
148
|
+
setRssResponse(
|
|
149
|
+
this.ctx,
|
|
150
|
+
buildRssXml({
|
|
151
|
+
title,
|
|
152
|
+
link: siteUrl,
|
|
153
|
+
description,
|
|
154
|
+
items,
|
|
155
|
+
}),
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
};
|
package/src/controller/token.js
CHANGED
|
@@ -17,7 +17,9 @@ module.exports = class extends BaseRest {
|
|
|
17
17
|
const { email, password, code } = this.post();
|
|
18
18
|
const user = await this.modelInstance.select({ email });
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
const isVerifyUser = /^verify:/i.test(user?.[0]?.type);
|
|
21
|
+
const isBannedUser = user?.[0]?.type === 'banned';
|
|
22
|
+
if (think.isEmpty(user) || isVerifyUser || isBannedUser) {
|
|
21
23
|
return this.fail();
|
|
22
24
|
}
|
|
23
25
|
|
package/src/controller/user.js
CHANGED
|
@@ -179,6 +179,27 @@ module.exports = class UserController extends BaseRest {
|
|
|
179
179
|
return this.success();
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
+
async deleteAction() {
|
|
183
|
+
const users = await this.modelInstance.select({
|
|
184
|
+
objectId: this.id,
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
if (think.isEmpty(users)) {
|
|
188
|
+
return this.fail();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const user = users[0];
|
|
192
|
+
const isVerifyUser = /^verify:/i.test(user.type);
|
|
193
|
+
|
|
194
|
+
if (isVerifyUser) {
|
|
195
|
+
await this.modelInstance.delete({ objectId: this.id });
|
|
196
|
+
} else {
|
|
197
|
+
await this.modelInstance.update({ type: 'banned' }, { objectId: this.id });
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return this.success();
|
|
201
|
+
}
|
|
202
|
+
|
|
182
203
|
// oxlint-disable-next-line max-statements
|
|
183
204
|
async getUsersListByCount() {
|
|
184
205
|
const { pageSize } = this.get();
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"import data format not support!": "Dateiformat wird nicht unterstützt",
|
|
3
|
+
"USER_EXIST": "Benutzer existiert bereits",
|
|
4
|
+
"USER_NOT_EXIST": "Benutzer existiert nicht",
|
|
5
|
+
"USER_REGISTERED": "Benutzer bereits registriert",
|
|
6
|
+
"TOKEN_EXPIRED": "Token ist abgelaufen",
|
|
7
|
+
"TWO_FACTOR_AUTH_ERROR_DETAIL": "Fehler bei der Zwei-Faktor-Authentifizierung",
|
|
8
|
+
"[{{name | safe}}] Registration Confirm Mail": "【{{name | safe}}】 Registrierungsbestätigung",
|
|
9
|
+
"Please click <a href=\"{{url}}\">{{url}}<a/> to confirm registration, the link is valid for 1 hour. If you are not registering, please ignore this email.": "Bitte klicken Sie auf <a href=\"{{url}}\">{{url}}</a>, um die Registrierung zu bestätigen. Der Link ist 1 Stunde gültig. Falls Sie sich nicht registriert haben, ignorieren Sie diese E-Mail.",
|
|
10
|
+
"[{{name | safe}}] Reset Password": "【{{name | safe}}】 Passwort zurücksetzen",
|
|
11
|
+
"Please click <a href=\"{{url}}\">{{url}}</a> to login and change your password as soon as possible!": "Bitte klicken Sie auf <a href=\"{{url}}\">{{url}}</a>, um sich anzumelden und Ihr Passwort so schnell wie möglich zu ändern!",
|
|
12
|
+
"Duplicate Content": "Doppelter Inhalt gesendet",
|
|
13
|
+
"Comment too fast": "Sie kommentieren zu schnell, bitte warten Sie einen Moment!",
|
|
14
|
+
"Registration confirm mail send failed, please {%- if isAdmin -%}check your mail configuration{%- else -%}check your email address and contact administrator{%- endif -%}.": "Fehler beim Senden der Registrierungsbestätigung. Bitte {%- if isAdmin -%}überprüfen Sie Ihre Mail-Konfiguration{%- else -%}prüfen Sie Ihre E-Mail-Adresse und kontaktieren Sie den Administrator{%- endif -%}.",
|
|
15
|
+
"MAIL_SUBJECT": "{{parent.nick | safe}},Sie haben eine Antwort auf ' {{site.name | safe}} ' erhalten",
|
|
16
|
+
"MAIL_TEMPLATE": "<div style='border-top:2px solid #12ADDB;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;margin:50px auto;font-size:12px;'> <h2 style='border-bottom:1px solid #DDD;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;'> Ihr Kommentar auf <a style='text-decoration:none;color: #12ADDB;' href='{{site.url}}' target='_blank'>{{site.name}}</a> hat eine neue Antwort </h2>{{parent.nick}}, Sie haben kommentiert: <div style='padding:0 12px 0 12px;margin-top:18px'> <div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{parent.comment | safe}}</div><p><strong>{{self.nick}}</strong> hat geantwortet:</p><div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{self.comment | safe}}</div><p>Sie können die vollständige Antwort ansehen unter <a style='text-decoration:none; color:#12addb' href='{{site.postUrl}}' target='_blank'>hier</a> und besuchen Sie erneut <a style='text-decoration:none; color:#12addb' href='{{site.url}}' target='_blank'>{{site.name}}</a>.</p><br/> </div></div>",
|
|
17
|
+
"MAIL_SUBJECT_ADMIN": "Neue Kommentare auf {{site.name | safe}}",
|
|
18
|
+
"MAIL_TEMPLATE_ADMIN": "<div style='border-top:2px solid #12ADDB;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;margin:50px auto;font-size:12px;'> <h2 style='border-bottom:1px solid #DDD;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;'> Ihr Artikel auf <a style='text-decoration:none;color: #12ADDB;' href='{{site.url}}' target='_blank'>{{site.name}}</a> hat neue Kommentare </h2> <p><strong>{{self.nick}}</strong> hat geantwortet:</p><div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{self.comment | safe}}</div><p>Sie können die Antwort vollständig ansehen unter <a style='text-decoration:none; color:#12addb' href='{{site.postUrl}}' target='_blank'>hier</a></p><br/> </div>"
|
|
19
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"import data format not support!": "Formato de archivo no compatible",
|
|
3
|
+
"USER_EXIST": "El usuario ya existe",
|
|
4
|
+
"USER_NOT_EXIST": "El usuario no existe",
|
|
5
|
+
"USER_REGISTERED": "Usuario ya registrado",
|
|
6
|
+
"TOKEN_EXPIRED": "El token ha expirado",
|
|
7
|
+
"TWO_FACTOR_AUTH_ERROR_DETAIL": "Error de autenticación en dos pasos",
|
|
8
|
+
"[{{name | safe}}] Registration Confirm Mail": "【{{name | safe}}】Correo de confirmación de registro",
|
|
9
|
+
"Please click <a href=\"{{url}}\">{{url}}<a/> to confirm registration, the link is valid for 1 hour. If you are not registering, please ignore this email.": "Por favor haga clic en <a href=\"{{url}}\">{{url}}</a> para confirmar el registro. El enlace es válido por 1 hora. Si no se ha registrado, ignore este correo.",
|
|
10
|
+
"[{{name | safe}}] Reset Password": "【{{name | safe}}】Restablecer contraseña",
|
|
11
|
+
"Please click <a href=\"{{url}}\">{{url}}</a> to login and change your password as soon as possible!": "Por favor haga clic en <a href=\"{{url}}\">{{url}}</a> para iniciar sesión y cambiar su contraseña lo antes posible!",
|
|
12
|
+
"Duplicate Content": "Contenido duplicado enviado",
|
|
13
|
+
"Comment too fast": "Comentarios muy rápidos, por favor espere un momento!",
|
|
14
|
+
"Registration confirm mail send failed, please {%- if isAdmin -%}check your mail configuration{%- else -%}check your email address and contact administrator{%- endif -%}.": "Error al enviar el correo de confirmación. Por favor {%- if isAdmin -%}verifique su configuración de correo{%- else -%}verifique su dirección de correo y contacte al administrador{%- endif -%}.",
|
|
15
|
+
"MAIL_SUBJECT": "{{parent.nick | safe}},Su comentario en '{{site.name | safe}}' ha recibido una respuesta",
|
|
16
|
+
"MAIL_TEMPLATE": "<div style='border-top:2px solid #12ADDB;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;margin:50px auto;font-size:12px;'> <h2 style='border-bottom:1px solid #DDD;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;'> Su comentario en <a style='text-decoration:none;color: #12ADDB;' href='{{site.url}}' target='_blank'>{{site.name}}</a> tiene una nueva respuesta </h2>{{parent.nick}}, usted comentó: <div style='padding:0 12px 0 12px;margin-top:18px'> <div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{parent.comment | safe}}</div><p><strong>{{self.nick}}</strong> respondió:</p><div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{self.comment | safe}}</div><p>Puedes ver la respuesta completa en <a style='text-decoration:none; color:#12addb' href='{{site.postUrl}}' target='_blank'>aquí</a>, y visita de nuevo <a style='text-decoration:none; color:#12addb' href='{{site.url}}' target='_blank'>{{site.name}}</a>.</p><br/> </div></div>",
|
|
17
|
+
"MAIL_SUBJECT_ADMIN": "Nuevo comentario en {{site.name | safe}}",
|
|
18
|
+
"MAIL_TEMPLATE_ADMIN": "<div style='border-top:2px solid #12ADDB;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;margin:50px auto;font-size:12px;'> <h2 style='border-bottom:1px solid #DDD;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;'> Su artículo en <a style='text-decoration:none;color: #12ADDB;' href='{{site.url}}' target='_blank'>{{site.name}}</a> tiene nuevos comentarios </h2> <p><strong>{{self.nick}}</strong> dijo:</p><div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{self.comment | safe}}</div><p>Puedes ver la respuesta completa en <a style='text-decoration:none; color:#12addb' href='{{site.postUrl}}' target='_blank'>aquí</a></p><br/> </div>"
|
|
19
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"import data format not support!": "Format de fichier non pris en charge",
|
|
3
|
+
"USER_EXIST": "L'utilisateur existe déjà",
|
|
4
|
+
"USER_NOT_EXIST": "L'utilisateur n'existe pas",
|
|
5
|
+
"USER_REGISTERED": "Utilisateur déjà enregistré",
|
|
6
|
+
"TOKEN_EXPIRED": "Le jeton a expiré",
|
|
7
|
+
"TWO_FACTOR_AUTH_ERROR_DETAIL": "Échec de l'authentification à deux facteurs",
|
|
8
|
+
"[{{name | safe}}] Registration Confirm Mail": "【{{name | safe}}】Mail de confirmation d'inscription",
|
|
9
|
+
"Please click <a href=\"{{url}}\">{{url}}<a/> to confirm registration, the link is valid for 1 hour. If you are not registering, please ignore this email.": "Veuillez cliquer sur <a href=\"{{url}}\">{{url}}</a> pour confirmer l'inscription. Le lien est valable 1 heure. Si vous ne vous êtes pas inscrit, ignorez cet e-mail.",
|
|
10
|
+
"[{{name | safe}}] Reset Password": "【{{name | safe}}】Réinitialisation du mot de passe",
|
|
11
|
+
"Please click <a href=\"{{url}}\">{{url}}</a> to login and change your password as soon as possible!": "Veuillez cliquer sur <a href=\"{{url}}\">{{url}}</a> pour vous connecter et changer votre mot de passe dès que possible !",
|
|
12
|
+
"Duplicate Content": "Contenu dupliqué envoyé",
|
|
13
|
+
"Comment too fast": "Vous commentez trop rapidement, veuillez ralentir !",
|
|
14
|
+
"Registration confirm mail send failed, please {%- if isAdmin -%}check your mail configuration{%- else -%}check your email address and contact administrator{%- endif -%}.": "Échec de l'envoi du mail de confirmation. Veuillez {%- if isAdmin -%}vérifier votre configuration d'e-mail{%- else -%}vérifier votre adresse e-mail et contacter l'administrateur{%- endif -%}.",
|
|
15
|
+
"MAIL_SUBJECT": "{{parent.nick | safe}},Votre commentaire sur '{{site.name | safe}}' a reçu une réponse",
|
|
16
|
+
"MAIL_TEMPLATE": "<div style='border-top:2px solid #12ADDB;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;margin:50px auto;font-size:12px;'> <h2 style='border-bottom:1px solid #DDD;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;'> Votre commentaire sur <a style='text-decoration:none;color: #12ADDB;' href='{{site.url}}' target='_blank'>{{site.name}}</a> a une nouvelle réponse </h2>{{parent.nick}}, vous avez commenté : <div style='padding:0 12px 0 12px;margin-top:18px'> <div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{parent.comment | safe}}</div><p><strong>{{self.nick}}</strong> a répondu :</p><div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{self.comment | safe}}</div><p>Vous pouvez voir la réponse complète <a style='text-decoration:none; color:#12addb' href='{{site.postUrl}}' target='_blank'>ici</a>, et revenez visiter <a style='text-decoration:none; color:#12addb' href='{{site.url}}' target='_blank'>{{site.name}}</a>.</p><br/> </div></div>",
|
|
17
|
+
"MAIL_SUBJECT_ADMIN": "Nouveau commentaire sur {{site.name | safe}}",
|
|
18
|
+
"MAIL_TEMPLATE_ADMIN": "<div style='border-top:2px solid #12ADDB;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;margin:50px auto;font-size:12px;'> <h2 style='border-bottom:1px solid #DDD;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;'> Votre article sur <a style='text-decoration:none;color: #12ADDB;' href='{{site.url}}' target='_blank'>{{site.name}}</a> a de nouveaux commentaires </h2> <p><strong>{{self.nick}}</strong> a écrit :</p><div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{self.comment | safe}}</div><p>Vous pouvez voir la réponse complète <a style='text-decoration:none; color:#12addb' href='{{site.postUrl}}' target='_blank'>ici</a></p><br/> </div>"
|
|
19
|
+
}
|
package/src/locales/index.js
CHANGED
|
@@ -2,14 +2,33 @@ const en = require('./en.json');
|
|
|
2
2
|
const it = require('./it.json');
|
|
3
3
|
const zhCN = require('./zh-CN.json');
|
|
4
4
|
const zhTW = require('./zh-TW.json');
|
|
5
|
+
const jp = require('./jp.json');
|
|
6
|
+
const koKR = require('./ko-KR.json');
|
|
7
|
+
const de = require('./de.json');
|
|
8
|
+
const esMX = require('./es.json');
|
|
9
|
+
const fr = require('./fr.json');
|
|
10
|
+
const ru = require('./ru.json');
|
|
11
|
+
const vi = require('./vi-VN.json');
|
|
12
|
+
const ptBR = require('./pt-BR.json');
|
|
5
13
|
|
|
6
14
|
module.exports = {
|
|
7
15
|
'zh-cn': zhCN,
|
|
8
16
|
'zh-tw': zhTW,
|
|
9
17
|
en: en,
|
|
10
18
|
'en-us': en,
|
|
11
|
-
jp: en,
|
|
12
|
-
'jp-jp': en,
|
|
13
19
|
it,
|
|
14
20
|
'it-it': it,
|
|
21
|
+
jp,
|
|
22
|
+
'jp-jp': jp,
|
|
23
|
+
ko: koKR,
|
|
24
|
+
'ko-kr': koKR,
|
|
25
|
+
de,
|
|
26
|
+
esMX,
|
|
27
|
+
fr,
|
|
28
|
+
'fr-fr': fr,
|
|
29
|
+
ru,
|
|
30
|
+
'ru-ru': ru,
|
|
31
|
+
vi,
|
|
32
|
+
'vi-vn': vi,
|
|
33
|
+
'pt-br': ptBR,
|
|
15
34
|
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"import data format not support!": "ファイル形式はサポートされていません",
|
|
3
|
+
"USER_EXIST": "ユーザーは既に存在します",
|
|
4
|
+
"USER_NOT_EXIST": "ユーザーが存在しません",
|
|
5
|
+
"USER_REGISTERED": "ユーザーは既に登録されています",
|
|
6
|
+
"TOKEN_EXPIRED": "トークンの有効期限が切れています",
|
|
7
|
+
"TWO_FACTOR_AUTH_ERROR_DETAIL": "二段階認証に失敗しました",
|
|
8
|
+
"[{{name | safe}}] Registration Confirm Mail": "【{{name | safe}}】 登録確認メール",
|
|
9
|
+
"Please click <a href=\"{{url}}\">{{url}}<a/> to confirm registration, the link is valid for 1 hour. If you are not registering, please ignore this email.": "登録を確認するには <a href=\"{{url}}\">{{url}}</a> をクリックしてください。リンクの有効期限は1時間です。登録していない場合は、このメールを無視してください。",
|
|
10
|
+
"[{{name | safe}}] Reset Password": "【{{name | safe}}】 パスワードリセット",
|
|
11
|
+
"Please click <a href=\"{{url}}\">{{url}}</a> to login and change your password as soon as possible!": "できるだけ早く <a href=\"{{url}}\">{{url}}</a> をクリックしてログインし、パスワードを変更してください!",
|
|
12
|
+
"Duplicate Content": "重複した内容が送信されました",
|
|
13
|
+
"Comment too fast": "コメントが速すぎます。少し待ってください!",
|
|
14
|
+
"Registration confirm mail send failed, please {%- if isAdmin -%}check your mail configuration{%- else -%}check your email address and contact administrator{%- endif -%}.": "登録確認メールの送信に失敗しました。{%- if isAdmin -%}メール設定を確認してください{%- else -%}メールアドレスを確認し、管理者に連絡してください{%- endif -%}。",
|
|
15
|
+
"MAIL_SUBJECT": "{{parent.nick | safe}}、『{{site.name | safe}}』にあなたのコメントへの返信があります",
|
|
16
|
+
"MAIL_TEMPLATE": "<div style='border-top:2px solid #12ADDB;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;margin:50px auto;font-size:12px;'> <h2 style='border-bottom:1px solid #DDD;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;'> <a style='text-decoration:none;color: #12ADDB;' href='{{site.url}}' target='_blank'>{{site.name}}</a> にあなたのコメントへの新しい返信があります </h2>{{parent.nick}}さん、あなたは次のようにコメントしました: <div style='padding:0 12px 0 12px;margin-top:18px'> <div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{parent.comment | safe}}</div><p><strong>{{self.nick}}</strong> が次のように返信しました:</p><div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{self.comment | safe}}</div><p>返信の全文は <a style='text-decoration:none; color:#12addb' href='{{site.postUrl}}' target='_blank'>こちら</a> で確認できます。<a style='text-decoration:none; color:#12addb' href='{{site.url}}' target='_blank'>{{site.name}}</a> にまたお越しください。</p><br/> </div></div>",
|
|
17
|
+
"MAIL_SUBJECT_ADMIN": "{{site.name | safe}} に新しいコメントがあります",
|
|
18
|
+
"MAIL_TEMPLATE_ADMIN": "<div style='border-top:2px solid #12ADDB;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;margin:50px auto;font-size:12px;'> <h2 style='border-bottom:1px solid #DDD;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;'> <a style='text-decoration:none;color: #12ADDB;' href='{{site.url}}' target='_blank'>{{site.name}}</a> に新しいコメントがあります </h2> <p><strong>{{self.nick}}</strong> が次のようにコメントしました:</p><div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{self.comment | safe}}</div><p>全文は <a style='text-decoration:none; color:#12addb' href='{{site.postUrl}}' target='_blank'>こちら</a> で確認できます。</p><br/> </div>"
|
|
19
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"import data format not support!": "가져오기 데이터 형식이 지원되지 않습니다!",
|
|
3
|
+
"USER_EXIST": "이미 존재하는 사용자입니다",
|
|
4
|
+
"USER_NOT_EXIST": "사용자가 존재하지 않습니다",
|
|
5
|
+
"USER_REGISTERED": "사용자가 등록되었습니다",
|
|
6
|
+
"TOKEN_EXPIRED": "토큰이 만료되었습니다",
|
|
7
|
+
"TWO_FACTOR_AUTH_ERROR_DETAIL": "2단계 인증 오류 상세",
|
|
8
|
+
"[{{name | safe}}] Registration Confirm Mail": "[{{name | safe}}] 가입 확인 메일",
|
|
9
|
+
"Please click <a href=\"{{url}}\">{{url}}<a/> to confirm registration, the link is valid for 1 hour. If you are not registering, please ignore this email.": "<a href=\"{{url}}\">{{url}}</a>을 클릭하여 가입을 확인해 주세요. 링크는 1시간 동안 유효합니다. 가입하지 않으셨다면 이 이메일을 무시해 주세요.",
|
|
10
|
+
"[{{name | safe}}] Reset Password": "[{{name | safe}}] 비밀번호 재설정",
|
|
11
|
+
"Please click <a href=\"{{url}}\">{{url}}</a> to login and change your password as soon as possible!": "<a href=\"{{url}}\">{{url}}</a>을 클릭하여 로그인하고 가능한 빨리 비밀번호를 변경해 주세요!",
|
|
12
|
+
"Duplicate Content": "중복된 내용",
|
|
13
|
+
"Comment too fast": "댓글 작성이 너무 빠릅니다",
|
|
14
|
+
"Registration confirm mail send failed, please {%- if isAdmin -%}check your mail configuration{%- else -%}check your email address and contact administrator{%- endif -%}.": "가입 확인 메일 발송에 실패했습니다. {%- if isAdmin -%}메일 설정을 확인해 주세요{%- else -%}이메일 주소를 확인하고 관리자에게 문의해 주세요{%- endif -%}.",
|
|
15
|
+
"MAIL_SUBJECT": "{{site.name | safe}}에서 댓글에 답글이 달렸습니다",
|
|
16
|
+
"MAIL_TEMPLATE": "<div style='border-top:2px solid #12ADDB;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;margin:50px auto;font-size:12px;'> <h2 style='border-bottom:1px solid #DDD;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;'> <a style='text-decoration:none;color: #12ADDB;' href='{{site.url}}' target='_blank'>{{site.name}}</a>에서 댓글에 답글이 달렸습니다 </h2>{{parent.nick}}님이 작성한 댓글: <div style='padding:0 12px 0 12px;margin-top:18px'> <div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{parent.comment | safe}}</div><p><strong>{{self.nick}}</strong>님이 답글을 남겼습니다:</p><div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{self.comment | safe}}</div><p><a style='text-decoration:none; color:#12addb' href='{{site.postUrl}}' target='_blank'>전체 답글 보기</a> 또는 <a style='text-decoration:none; color:#12addb' href='{{site.url}}' target='_blank'>{{site.name}}</a> 방문.</p><br/> </div></div>",
|
|
17
|
+
"MAIL_SUBJECT_ADMIN": "{{site.name | safe}}에 새 댓글이 달렸습니다",
|
|
18
|
+
"MAIL_TEMPLATE_ADMIN": "<div style='border-top:2px solid #12ADDB;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;margin:50px auto;font-size:12px;'> <h2 style='border-bottom:1px solid #DDD;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;'> <a style='text-decoration:none;color: #12ADDB;' href='{{site.url}}' target='_blank'>{{site.name}}</a>에 새 댓글이 달렸습니다 </h2> <p><strong>{{self.nick}}</strong>님이 작성했습니다:</p><div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{self.comment | safe}}</div><p><a style='text-decoration:none; color:#12addb' href='{{site.postUrl}}' target='_blank'>페이지 보기</a></p><br/></div>"
|
|
19
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"import data format not support!": "Formato de arquivo não suportado",
|
|
3
|
+
"USER_EXIST": "Usuário já existe",
|
|
4
|
+
"USER_NOT_EXIST": "Usuário não existe",
|
|
5
|
+
"USER_REGISTERED": "Usuário já registrado",
|
|
6
|
+
"TOKEN_EXPIRED": "Token expirou",
|
|
7
|
+
"TWO_FACTOR_AUTH_ERROR_DETAIL": "Erro de autenticação em dois fatores",
|
|
8
|
+
"[{{name | safe}}] Registration Confirm Mail": "【{{name | safe}}】Confirmação de registro",
|
|
9
|
+
"Please click <a href=\"{{url}}\">{{url}}<a/> to confirm registration, the link is valid for 1 hour. If you are not registering, please ignore this email.": "Por favor clique em <a href=\"{{url}}\">{{url}}</a> para confirmar o registro. O link é válido por 1 hora. Se você não está registrando, ignore este e-mail.",
|
|
10
|
+
"[{{name | safe}}] Reset Password": "【{{name | safe}}】Redefinir senha",
|
|
11
|
+
"Please click <a href=\"{{url}}\">{{url}}</a> to login and change your password as soon as possible!": "Por favor clique em <a href=\"{{url}}\">{{url}}</a> para entrar e alterar sua senha o quanto antes!",
|
|
12
|
+
"Duplicate Content": "Conteúdo duplicado enviado",
|
|
13
|
+
"Comment too fast": "Comentando rápido demais, por favor aguarde!",
|
|
14
|
+
"Registration confirm mail send failed, please {%- if isAdmin -%}check your mail configuration{%- else -%}check your email address and contact administrator{%- endif -%}.": "Falha ao enviar o e-mail de confirmação. Por favor {%- if isAdmin -%}verifique a configuração de e-mail{%- else -%}verifique seu endereço de e-mail e contate o administrador{%- endif -%}.",
|
|
15
|
+
"MAIL_SUBJECT": "{{parent.nick | safe}},Seu comentário em '{{site.name | safe}}' recebeu uma resposta",
|
|
16
|
+
"MAIL_TEMPLATE": "<div style='border-top:2px solid #12ADDB;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;margin:50px auto;font-size:12px;'> <h2 style='border-bottom:1px solid #DDD;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;'> Seu comentário em <a style='text-decoration:none;color: #12ADDB;' href='{{site.url}}' target='_blank'>{{site.name}}</a> tem uma nova resposta </h2>{{parent.nick}}, você comentou: <div style='padding:0 12px 0 12px;margin-top:18px'> <div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{parent.comment | safe}}</div><p><strong>{{self.nick}}</strong> respondeu:</p><div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{self.comment | safe}}</div><p>Você pode ver a resposta completa em <a style='text-decoration:none; color:#12addb' href='{{site.postUrl}}' target='_blank'>aqui</a>, e visite novamente <a style='text-decoration:none; color:#12addb' href='{{site.url}}' target='_blank'>{{site.name}}</a>.</p><br/> </div></div>",
|
|
17
|
+
"MAIL_SUBJECT_ADMIN": "Novo comentário em {{site.name | safe}}",
|
|
18
|
+
"MAIL_TEMPLATE_ADMIN": "<div style='border-top:2px solid #12ADDB;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;margin:50px auto;font-size:12px;'> <h2 style='border-bottom:1px solid #DDD;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;'> Seu artigo em <a style='text-decoration:none;color: #12ADDB;' href='{{site.url}}' target='_blank'>{{site.name}}</a> tem novos comentários </h2> <p><strong>{{self.nick}}</strong> disse:</p><div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{self.comment | safe}}</div><p>Você pode ver a resposta completa em <a style='text-decoration:none; color:#12addb' href='{{site.postUrl}}' target='_blank'>aqui</a></p><br/> </div>"
|
|
19
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"import data format not support!": "Формат файла не поддерживается",
|
|
3
|
+
"USER_EXIST": "Пользователь уже существует",
|
|
4
|
+
"USER_NOT_EXIST": "Пользователь не найден",
|
|
5
|
+
"USER_REGISTERED": "Пользователь уже зарегистрирован",
|
|
6
|
+
"TOKEN_EXPIRED": "Токен истёк",
|
|
7
|
+
"TWO_FACTOR_AUTH_ERROR_DETAIL": "Ошибка двухфакторной аутентификации",
|
|
8
|
+
"[{{name | safe}}] Registration Confirm Mail": "【{{name | safe}}】Письмо подтверждения регистрации",
|
|
9
|
+
"Please click <a href=\"{{url}}\">{{url}}<a/> to confirm registration, the link is valid for 1 hour. If you are not registering, please ignore this email.": "Пожалуйста, нажмите <a href=\"{{url}}\">{{url}}</a>, чтобы подтвердить регистрацию. Ссылка действительна 1 час. Если вы не регистрировались, проигнорируйте это письмо.",
|
|
10
|
+
"[{{name | safe}}] Reset Password": "【{{name | safe}}】Сброс пароля",
|
|
11
|
+
"Please click <a href=\"{{url}}\">{{url}}</a> to login and change your password as soon as possible!": "Пожалуйста, нажмите <a href=\"{{url}}\">{{url}}</a>, чтобы войти и сменить пароль как можно скорее!",
|
|
12
|
+
"Duplicate Content": "Дублированное содержание",
|
|
13
|
+
"Comment too fast": "Слишком быстрое комментирование, пожалуйста, замедлитесь!",
|
|
14
|
+
"Registration confirm mail send failed, please {%- if isAdmin -%}check your mail configuration{%- else -%}check your email address and contact administrator{%- endif -%}.": "Сбой отправки письма подтверждения регистрации. Пожалуйста, {%- if isAdmin -%}проверьте конфигурацию почты{%- else -%}проверьте адрес эл. почты и свяжитесь с администратором{%- endif -%}.",
|
|
15
|
+
"MAIL_SUBJECT": "{{parent.nick | safe}},У вас есть ответ на комментарий в '{{site.name | safe}}'",
|
|
16
|
+
"MAIL_TEMPLATE": "<div style='border-top:2px solid #12ADDB;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;margin:50px auto;font-size:12px;'> <h2 style='border-bottom:1px solid #DDD;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;'> Ваш комментарий на <a style='text-decoration:none;color: #12ADDB;' href='{{site.url}}' target='_blank'>{{site.name}}</a> получил новый ответ </h2>{{parent.nick}}, вы писали: <div style='padding:0 12px 0 12px;margin-top:18px'> <div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{parent.comment | safe}}</div><p><strong>{{self.nick}}</strong> ответил:</p><div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{self.comment | safe}}</div><p>Просмотреть полный ответ можно по ссылке <a style='text-decoration:none; color:#12addb' href='{{site.postUrl}}' target='_blank'>здесь</a>, и посетите снова <a style='text-decoration:none; color:#12addb' href='{{site.url}}' target='_blank'>{{site.name}}</a>.</p><br/> </div></div>",
|
|
17
|
+
"MAIL_SUBJECT_ADMIN": "Новый комментарий на {{site.name | safe}}",
|
|
18
|
+
"MAIL_TEMPLATE_ADMIN": "<div style='border-top:2px solid #12ADDB;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;margin:50px auto;font-size:12px;'> <h2 style='border-bottom:1px solid #DDD;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;'> В вашей статье на <a style='text-decoration:none;color: #12ADDB;' href='{{site.url}}' target='_blank'>{{site.name}}</a> новый комментарий </h2> <p><strong>{{self.nick}}</strong> написал:</p><div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{self.comment | safe}}</div><p>Просмотреть полностью: <a style='text-decoration:none; color:#12addb' href='{{site.postUrl}}' target='_blank'>здесь</a></p><br/> </div>"
|
|
19
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"import data format not support!": "Định dạng tệp không được hỗ trợ",
|
|
3
|
+
"USER_EXIST": "Người dùng đã tồn tại",
|
|
4
|
+
"USER_NOT_EXIST": "Người dùng không tồn tại",
|
|
5
|
+
"USER_REGISTERED": "Người dùng đã đăng ký",
|
|
6
|
+
"TOKEN_EXPIRED": "Mã thông báo đã hết hạn",
|
|
7
|
+
"TWO_FACTOR_AUTH_ERROR_DETAIL": "Xác thực hai bước thất bại",
|
|
8
|
+
"[{{name | safe}}] Registration Confirm Mail": "【{{name | safe}}】 Thư xác nhận đăng ký",
|
|
9
|
+
"Please click <a href=\"{{url}}\">{{url}}<a/> to confirm registration, the link is valid for 1 hour. If you are not registering, please ignore this email.": "Vui lòng nhấp vào <a href=\"{{url}}\">{{url}}</a> để xác nhận đăng ký. Liên kết có hiệu lực trong 1 giờ. Nếu bạn không đăng ký, hãy bỏ qua email này.",
|
|
10
|
+
"[{{name | safe}}] Reset Password": "【{{name | safe}}】 Đặt lại mật khẩu",
|
|
11
|
+
"Please click <a href=\"{{url}}\">{{url}}</a> to login and change your password as soon as possible!": "Vui lòng nhấp vào <a href=\"{{url}}\">{{url}}</a> để đăng nhập và thay đổi mật khẩu càng sớm càng tốt!",
|
|
12
|
+
"Duplicate Content": "Nội dung trùng lặp đã được gửi",
|
|
13
|
+
"Comment too fast": "Bình luận quá nhanh, vui lòng chậm lại!",
|
|
14
|
+
"Registration confirm mail send failed, please {%- if isAdmin -%}check your mail configuration{%- else -%}check your email address and contact administrator{%- endif -%}.": "Gửi mail xác nhận đăng ký thất bại. Vui lòng {%- if isAdmin -%}kiểm tra cấu hình mail{%- else -%}kiểm tra địa chỉ email và liên hệ quản trị viên{%- endif -%}.",
|
|
15
|
+
"MAIL_SUBJECT": "{{parent.nick | safe}},Bình luận của bạn trên '{{site.name | safe}}' đã có phản hồi",
|
|
16
|
+
"MAIL_TEMPLATE": "<div style='border-top:2px solid #12ADDB;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;margin:50px auto;font-size:12px;'> <h2 style='border-bottom:1px solid #DDD;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;'> Bình luận của bạn trên <a style='text-decoration:none;color: #12ADDB;' href='{{site.url}}' target='_blank'>{{site.name}}</a> đã có phản hồi </h2>{{parent.nick}}, bạn đã bình luận: <div style='padding:0 12px 0 12px;margin-top:18px'> <div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{parent.comment | safe}}</div><p><strong>{{self.nick}}</strong> trả lời:</p><div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{self.comment | safe}}</div><p>Bạn có thể xem phản hồi đầy đủ tại <a style='text-decoration:none; color:#12addb' href='{{site.postUrl}}' target='_blank'>đây</a>, và ghé thăm lại <a style='text-decoration:none; color:#12addb' href='{{site.url}}' target='_blank'>{{site.name}}</a>.</p><br/> </div></div>",
|
|
17
|
+
"MAIL_SUBJECT_ADMIN": "Bình luận mới trên {{site.name | safe}}",
|
|
18
|
+
"MAIL_TEMPLATE_ADMIN": "<div style='border-top:2px solid #12ADDB;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;margin:50px auto;font-size:12px;'> <h2 style='border-bottom:1px solid #DDD;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;'> Bài viết của bạn trên <a style='text-decoration:none;color: #12ADDB;' href='{{site.url}}' target='_blank'>{{site.name}}</a> có bình luận mới </h2> <p><strong>{{self.nick}}</strong> trả lời:</p><div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{self.comment | safe}}</div><p>Bạn có thể xem phản hồi đầy đủ tại <a style='text-decoration:none; color:#12addb' href='{{site.postUrl}}' target='_blank'>đây</a></p><br/> </div>"
|
|
19
|
+
}
|
package/src/logic/base.js
CHANGED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
const Base = require('../base.js');
|
|
2
|
+
|
|
3
|
+
module.exports = class extends Base {
|
|
4
|
+
/**
|
|
5
|
+
* @api {GET} /api/comment/rss Get site recent comments RSS
|
|
6
|
+
* @apiGroup Comment
|
|
7
|
+
* @apiVersion 0.0.1
|
|
8
|
+
*
|
|
9
|
+
* @apiParam {String} [count] return comments number, default value is 20
|
|
10
|
+
*
|
|
11
|
+
* @apiHeader {String} Content-Type application/rss+xml
|
|
12
|
+
* @apiSuccess (200) {String} body RSS 2.0 xml content
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* @api {GET} /api/comment/rss?path= Get comments RSS for a path
|
|
16
|
+
* @apiGroup Comment
|
|
17
|
+
* @apiVersion 0.0.1
|
|
18
|
+
*
|
|
19
|
+
* @apiParam {String} path comment url path
|
|
20
|
+
* @apiParam {String} [count] return comments number, default value is 20
|
|
21
|
+
*
|
|
22
|
+
* @apiHeader {String} Content-Type application/rss+xml
|
|
23
|
+
* @apiSuccess (200) {String} body RSS 2.0 xml content
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* @api {GET} /api/comment/rss?email=&user_id= Get reply comments RSS for user
|
|
27
|
+
* @apiGroup Comment
|
|
28
|
+
* @apiVersion 0.0.1
|
|
29
|
+
*
|
|
30
|
+
* @apiParam {String} [email] comment user email
|
|
31
|
+
* @apiParam {String} [user_id] comment user id
|
|
32
|
+
* @apiParam {String} [count] return comments number, default value is 20
|
|
33
|
+
*
|
|
34
|
+
* @apiHeader {String} Content-Type application/rss+xml
|
|
35
|
+
* @apiSuccess (200) {String} body RSS 2.0 xml content
|
|
36
|
+
*/
|
|
37
|
+
getAction() {
|
|
38
|
+
this.rules = {
|
|
39
|
+
path: {
|
|
40
|
+
string: true,
|
|
41
|
+
},
|
|
42
|
+
email: {
|
|
43
|
+
email: true,
|
|
44
|
+
},
|
|
45
|
+
user_id: {
|
|
46
|
+
string: true,
|
|
47
|
+
},
|
|
48
|
+
count: {
|
|
49
|
+
int: { max: 50 },
|
|
50
|
+
default: 20,
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
};
|
package/src/logic/user.js
CHANGED
|
@@ -121,4 +121,29 @@ module.exports = class extends Base {
|
|
|
121
121
|
},
|
|
122
122
|
};
|
|
123
123
|
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* @api {DELETE} /api/user delete user account when user is in verify status, or forbid user to login when user is other status.
|
|
127
|
+
* @apiGroup User
|
|
128
|
+
* @apiVersion 0.0.1
|
|
129
|
+
*
|
|
130
|
+
* @apiParam {String} id user id
|
|
131
|
+
* @apiParam {String} lang language
|
|
132
|
+
*
|
|
133
|
+
* @apiSuccess (200) {Number} errno 0
|
|
134
|
+
* @apiSuccess (200) {String} errmsg return error message if error
|
|
135
|
+
*/
|
|
136
|
+
deleteAction() {
|
|
137
|
+
// you need to be logged in to delete users
|
|
138
|
+
const { userInfo } = this.ctx.state;
|
|
139
|
+
|
|
140
|
+
if (think.isEmpty(userInfo)) {
|
|
141
|
+
return this.fail();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// you must be an administrator to delete other users and cannot delete yourself
|
|
145
|
+
if (userInfo.type !== 'administrator' || this.id === userInfo.objectId) {
|
|
146
|
+
return this.fail();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
124
149
|
};
|