Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add internationalization #60

Merged
merged 15 commits into from
Jul 14, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 73 additions & 7 deletions PvPCraft.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ for (let thing in Eris) {
}
}
}
const i10010n = require("i10010n");
const TaskQueue = require("./lib/TaskQueue");
const MessageSender = require("./lib/MessageSender");
const Permissions = require("./lib/Permissions.js");
Expand Down Expand Up @@ -89,8 +90,14 @@ class PvPCraft {
// this.rejectReadyPromise = reject;
});

this.captureMissingTranslation = this.captureMissingTranslation.bind(this);
this.getChannelLanguage = this.getChannelLanguage.bind(this);
this.translate = (channelID, guildID) =>
this.i10010n(this.getChannelLanguage(channelID, guildID));

Promise.resolve()
.then(this.loadAnalytics.bind(this))
.then(this.readyI10010n.bind(this))
.then(this.readyRaven.bind(this))
.then(this.registerProcessListeners.bind(this))
.then(this.readyRethinkDB.bind(this))
Expand Down Expand Up @@ -227,7 +234,7 @@ class PvPCraft {
}

readyMessageSender() {
this.messageSender = new MessageSender({client: this.client});
this.messageSender = new MessageSender({client: this.client, translate: this.translate});
}

readySlowSender() {
Expand All @@ -246,6 +253,14 @@ class PvPCraft {
return this.readyPromise;
}

readyI10010n() {
this.i10010n = i10010n.init({
db: require("./config/translations.db"),
logger: this.captureMissingTranslation,
addTemplateData: () => {},
});
}

readyPvPClient() {
const endpoint = this.fileAuth.get("pvpApiEndpoint", "api.pvpcraft.ca");
const https = this.fileAuth.get("pvpApiHttps", true);
Expand Down Expand Up @@ -470,7 +485,7 @@ class PvPCraft {
return new Promise((resolve) => {
this.configDB = new ConfigsDB(this.r, "servers", this.client);
this.permsDB = new ConfigsDB(this.r, "permissions", this.client);
this.perms = new Permissions(this.permsDB, this.analytics);
this.perms = new Permissions(this.permsDB, this.analytics, this.translate);
Promise.all([this.configDB.reload(), this.permsDB.reload()]).then(() => {
resolve(true);
}).catch(console.error);
Expand Down Expand Up @@ -533,6 +548,39 @@ class PvPCraft {
})
}

captureMissingTranslation(errorType, data, message) {
const errTypes = i10010n.ErrorTypes;
let level;

switch (errorType) {
case errTypes.MISSING_TEMPLATE_DATA:
level = "warning";
break;
case errTypes.MISSING_LOCALE_DATA:
level = "info";
break;
case errTypes.USER_FUNCTION_FAILED:
case errTypes.MISSING_DB:
case errTypes.MISSING_LOCALE:
default:
level = "error";
break;
}

this.raven.captureMessage(
errorType,
{
level,
tags: {
locale: data.locale,
user_function: data.user_function,
template: (data.template || []).join(",").replace(/\s/g, "-"),
},
extra: Object.assign({ message }, data)
}
);
}

shutDown() {
setTimeout(() => {
process.exit(1)
Expand Down Expand Up @@ -643,6 +691,8 @@ class PvPCraft {
modules: this.moduleList,
middleWares: this.middlewareList,
taskQueue: this.taskQueue,
i10010n: this.i10010n,
getChannelLanguage: this.getChannelLanguage,
};
}

Expand All @@ -654,15 +704,15 @@ class PvPCraft {
}
let modules = this.fileConfig.get("modules");
delete require.cache[require.resolve(modules[command.args[0]])];
utils.handleErisRejection(command.reply("Reloading " + command.args[0]));
utils.handleErisRejection(command.reply(command.translate `Reloading ${command.args[0]}`));
console.log("Reloading ".yellow + command.args[0].yellow);
let Mod = require(modules[command.args[0]]);
let mod = new Mod(this.getModuleVariables());
if (mod.onReady) mod.onReady();
this.moduleList[module].module = mod;
this.moduleList[module].commands = Mod.getCommands();
console.log("Reloded ".yellow + command.args[0].yellow);
utils.handleErisRejection(command.reply("Reloded " + command.args[0]));
utils.handleErisRejection(command.reply(command.translate `Reloded ${command.args[0]}`));
}
}
}
Expand Down Expand Up @@ -691,6 +741,8 @@ class PvPCraft {
allowMention: this.id,
botName: this.name,
raven: this.raven,
i10010n: this.i10010n,
getChannelLanguage: this.getChannelLanguage,
});
} catch (error) {
if (this.raven) {
Expand All @@ -711,7 +763,7 @@ class PvPCraft {
extra,
});
}
utils.handleErisRejection(msg.channel.createMessage(`${msg.author.mention}, Sorry about that an unknown problem occurred processing your command, an error report has been logged and we are looking into the problem.`));
utils.handleErisRejection(msg.channel.createMessage(this.translate(msg.channel.id) `${msg.author.mention}, Sorry about that an unknown problem occurred processing your command, an error report has been logged and we are looking into the problem.`));
}

for (let ware in this.middlewareList) {
Expand Down Expand Up @@ -831,8 +883,8 @@ class PvPCraft {
if (ravenError) {
console.error("Error reporting error to sentry:\n", ravenError, "Error sentry was trying to report:\n", ravenError);
} else {
utils.handleErisRejection(msg.channel.createMessage("Sorry, there was an error processing your command. The error is ```" + error +
"``` reference code `" + id + "`"));
utils.handleErisRejection(msg.channel.createMessage(this.translate(msg.channel.id) `Sorry, there was an error processing your command. The error is \`\`\`${error
}\`\`\` reference code \`${id}\``));
}
if (process.env.dev === "true") {
console.error(error);
Expand Down Expand Up @@ -862,6 +914,20 @@ class PvPCraft {
console.error(error);
}
}

getChannelLanguage(channelID, guildID) {
if (!guildID) {
guildID = this.client.channelGuildMap[channelID];
}
const languages = this.configDB.get("languages", null, {server: guildID});
if (languages.hasOwnProperty(channelID)) {
return languages[channelID];
}
if (languages.hasOwnProperty("*")) {
return languages["*"];
}
return "en";
}
}

module.exports = PvPCraft;
17 changes: 12 additions & 5 deletions lib/Command.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,10 @@ class Command {
* @param {string[]} flags flags run with command eg `-f`
* @param {Message} msg message that triggered the command object's creation
* @param {Permissions} perms Permission object
* @param {Function} translate internationalization function with bound language
* @param {Raven} [raven] Raven Sentry library
*/
constructor(command, commandNoS, prefix, args, options, flags, msg, perms, raven) {
constructor(command, commandNoS, prefix, args, options, flags, msg, perms, translate, raven) {
this.command = command;
this.commandnos = commandNoS;
this.prefix = prefix;
Expand All @@ -126,6 +127,7 @@ class Command {
this.author = msg.author;
this.raven = raven;
this.perms = perms;
this.translate = translate;

this.autoDenyPermission = this.autoDenyPermission.bind(this)
}
Expand Down Expand Up @@ -192,6 +194,8 @@ class Command {
* @param {Raven} [options.raven]
* @param {boolean} [options.allowMention]
* @param {string} [options.botName] bot's name, used as prefix if the bot is mentioned
* @param {Function} options.i10010n internationalization function
* @param {Function} options.getChannelLanguage function to get language of channel
* @returns {Command | boolean}
*/
static parse(prefix, message, perms, options = {}) {
Expand Down Expand Up @@ -227,6 +231,8 @@ class Command {
args[0] = args[0].toLowerCase();
}

const translate = options.i10010n(options.getChannelLanguage(message.channel.id));

let command = new Command(args[0],
removeTrailingS(args[0]),
prefixUsed,
Expand All @@ -235,6 +241,7 @@ class Command {
flags,
message,
perms,
translate,
options.raven,
);

Expand Down Expand Up @@ -375,9 +382,9 @@ class Command {
let owner = guild.members.get(guild.ownerID);
if (owner) {
owner.user.getDMChannel().then(channel =>
channel.createMessage(`Hello, I've removed and denied the permissions configuration for channel ` +
`${this.msg.channel.mention} on ${guild.name} as I didn't have permissions to send messages in ` +
`that channel. Please use /perms list on that server to see the new configuration.`),
channel.createMessage(this.translate `Hello, I've removed and denied the permissions configuration for channel ${
this.msg.channel.mention} on ${guild.name} as I didn't have permissions to send messages in that channel. \
Please use /perms list on that server to see the new configuration.`),
);
}
} else {
Expand Down Expand Up @@ -432,4 +439,4 @@ class Command {
}
}

module.exports = Command;
module.exports = Command;
4 changes: 3 additions & 1 deletion lib/MessageSender.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ class MessageSender {
* @constructor
* @param {Object} e
* @param {Eris} e.client
* @param {Function} e.translate
*/
constructor(e) {
this._client = e.client;
this._queuedMessages = {};
this.translate = e.translate;

//noinspection JSUnusedGlobalSymbols
this.hookSender = setInterval(this.emptyQueue.bind(this), 2500);
Expand Down Expand Up @@ -46,7 +48,7 @@ class MessageSender {
texts = calledOptions.text.match(/^.{1,1900}/g);
}
texts.forEach((string) => {
calledOptions.channel.createMessage(string + "\nPlease give the bot \"Manage Webhooks\" to enable non fallback functionality").catch(() => {});
calledOptions.channel.createMessage(this.translate(calledOptions.channel.id) `${string}\nPlease give the bot \"Manage Webhooks\" to enable non fallback functionality`).catch(() => {});
});
})
}
Expand Down
10 changes: 6 additions & 4 deletions lib/Permissions.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ class Permissions {
*
* @param {ConfigDB} permsDB
* @param analytics
* @param translate
*/
constructor(permsDB, analytics) {
constructor(permsDB, analytics, translate) {
this.perms = permsDB;
this._analytics = analytics;
this.translate = translate;
}

getCommands() {
Expand Down Expand Up @@ -70,9 +72,9 @@ class Permissions {
let owner = guild.members.get(guild.ownerID);
if (owner) {
owner.user.getDMChannel().then(channel =>
channel.createMessage(`Hello, I've removed and denied the permissions configuration for channel ` +
`${msg.channel.mention} on ${guild.name} as I didn't have permissions to send messages in ` +
`that channel. Please use /perms list on that server to see the new configuration.`),
channel.createMessage(this.translate(channel.id) `Hello, I've removed and denied the permissions configuration for channel ${
msg.channel.mention} on ${guild.name} as I didn't have permissions to send messages in that channel. \
Please use /perms list on that server to see the new configuration.`),
);
}
} else {
Expand Down
4 changes: 3 additions & 1 deletion lib/Player.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class Player extends EventEmitter {
* @param {R} e.r rethinkdb driver
* @param {SlowSender} e.slowSender
* @param {string} e.apiKey
* @param {Function} e.i10010n
*/
constructor(e) {
super();
Expand All @@ -65,6 +66,7 @@ class Player extends EventEmitter {
this.playNext = this.playNext.bind(this);
this.enqueueSong = this.enqueueSong.bind(this);
this._maybeLog = this._maybeLog.bind(this);
this.i10010n = e.i10010n;
}

/**
Expand Down Expand Up @@ -255,7 +257,7 @@ class Player extends EventEmitter {
stringError = stringError[0];
}
}
command.replyAutoDeny(`Sorry while fetching that I encountered the error: ${utils.clean(stringError)}.`);
command.replyAutoDeny(command.translate `Sorry while fetching that I encountered the error: ${utils.clean(stringError)}.`);
}

/**
Expand Down
1 change: 0 additions & 1 deletion lib/TaskQueue.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ class taskQueue {
}

processQueue(queue) {
console.log(queue);
queue.forEach(this.processTask);
}

Expand Down
9 changes: 6 additions & 3 deletions middleware/rateLimits.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@ class rateLimits {
* @param {MessageSender} e.messageSender Instantiated message sender
* @param {SlowSender} e.slowSender Instantiated slow sender
* @param {PvPClient} e.pvpClient PvPCraft client library instance
* @param {Function} e.i10010n
*/
constructor(e) {
this.client = e.client;

this.i10010n = e.i10010n;

this.channelRateLimitWhiteList = e.config.get("channelRateLimitWhiteList", []);

this.userCommandCount = {};
Expand Down Expand Up @@ -124,7 +127,7 @@ class rateLimits {
}
if (this.userCommandCount[msg.author.id] === this.userLimit + 1) {
this.userCommandCount[msg.author.id] += this.userLimit * 2;
command.reply("WOAH THERE. WAY TOO SPICY\nYou have exceeded the rate limit.");
command.reply(command.translate `WOAH THERE. WAY TOO SPICY\nYou have exceeded the rate limit.`);
console.log(`User ${msg.author.username} was rate Limited running command ${command.prefix}${command.command}, userId:${msg.author.id}`.magenta);
}
if (this.userCommandCount[msg.author.id] > this.userLimit) {
Expand All @@ -146,7 +149,7 @@ class rateLimits {
}
if (this.channelCommandCount[msg.channel.id] === this.channelLimit + 1) {
this.channelCommandCount[msg.channel.id] += this.channelLimit * 2;
command.reply("WOAH THERE. WAY TOO SPICY\nChannel has exceeded the rate limit.");
command.reply(command.translate `WOAH THERE. WAY TOO SPICY\nChannel has exceeded the rate limit.`);
console.log(`Channel ${msg.channel.name}:${msg.channel.id} was rate Limited running command ${command.prefix}${command.command} in ${msg.server.name}:${msg.server.id}`.magenta);
}
if (this.channelCommandCount[msg.channel.id] > this.channelLimit) {
Expand All @@ -163,7 +166,7 @@ class rateLimits {
}
if (this.serverCommandCount[msg.server.id] === this.serverLimit + 1) {
this.serverCommandCount[msg.server.id] += this.serverLimit * 2;
command.reply("WOAH THERE. WAY TOO SPICY\nServer has exceeded the rate limit.");
command.reply(command.translate `WOAH THERE. WAY TOO SPICY\nServer has exceeded the rate limit.`);
console.log(`Server ${msg.server.name}:${msg.server.id} was rate Limited running command ${command.prefix}${command.command}`.magenta);
}
if (this.serverCommandCount[msg.server.id] > this.serverLimit) {
Expand Down
Loading