i18n waterMe

This commit is contained in:
mo
2026-02-21 00:20:12 +01:00
parent d2e88f15ea
commit 453577f1b2
13 changed files with 144 additions and 78 deletions

View File

@@ -1,4 +1,9 @@
import { WaterMeService } from "@avocadi/bot-core/features/water-me/water-me.service";
import { i18nService } from "@avocadi/bot-core/lib/i18n";
import { messagesService } from "entitites/messages/messages.service";
export const waterMeService = new WaterMeService(messagesService);
export const waterMeService = new WaterMeService(
messagesService,
i18nService,
"de",
);

View File

@@ -3,5 +3,5 @@ import { logger } from "lib/common-logger";
export const handleShutdown = async () => {
logger.info("bot is shutting down...");
await logChannelService.sendLogMessage("ich geh schlafen...");
await logChannelService.sendLogMessage("**S H U T T I N G D O W N**");
};

View File

@@ -1,4 +1,9 @@
import { WaterMeService } from "@avocadi/bot-core/features/water-me/water-me.service";
import { i18nService } from "@avocadi/bot-core/lib/i18n";
import { messagesService } from "entities/messages/messages.service";
export const waterMeService = new WaterMeService(messagesService);
export const waterMeService = new WaterMeService(
messagesService,
i18nService,
"en",
);

View File

@@ -5,7 +5,7 @@ import client from "lib/client";
import { logger } from "lib/common-logger";
client.on(Events.Ready, async () => {
await logChannelService.sendLogMessage("wieder online!!!");
await logChannelService.sendLogMessage("**O N L I N E**");
logger.info("bot is online");

View File

@@ -21,6 +21,7 @@
"discord.js": "^14.16.3",
"dotenv": "^16.4.7",
"drizzle-orm": "^0.38.3",
"i18next": "^25.8.11",
"tslog": "^4.10.2",
"zod": "catalog:"
},
@@ -46,6 +47,8 @@
"./features/greeting/greeting.service": "./dist/features/greeting/greeting.service.js",
"./features/water-me/water-me.service": "./dist/features/water-me/water-me.service.js",
"./lib/common": "./dist/lib/common.js",
"./lib/i18n": "./dist/lib/i18n/index.js",
"./lib/i18n/i18n.service": "./dist/lib/i18n/i18n.service.js",
"./lib/logger": "./dist/lib/logger.js",
"./lib/utils": "./dist/lib/utils.js",
"./lib/utils.test": "./dist/lib/utils.test.js",

View File

@@ -1,42 +0,0 @@
export default {
discord: {
version: 251218,
// avocadi
serverID: process.env.DISCORD_SERVER_ID || "",
// text channel
channelIdBump: process.env.DISCORD_CHANNEL_ID_BUMP || "",
channelIdBot: process.env.DISCORD_CHANNEL_ID_BOT || "",
channelIdFeedback: process.env.DISCORD_CHANNEL_ID_FEEDBACK || "",
channelIdLog: process.env.DISCORD_CHANNEL_ID_NOTIFICATION || "",
channelIdWelcome: process.env.DISCORD_CHANNEL_ID_WELCOME || "",
channelIdRules: process.env.DISCORD_CHANNEL_ID_RULE || "",
channelIdNews: process.env.DISCORD_CHANNEL_ID_NEWS || "",
channelIdIntroduction: process.env.DISCORD_CHANNEL_ID_INTRODUCTION || "",
channelIdOffTopic: process.env.DISCORD_CHANNEL_ID_OFF_TOPIC || "",
channelIdHelp: process.env.DISCORD_CHANNEL_ID_HELP || "",
channelIdPomodoro: process.env.DISCORD_CHANNEL_ID_POMODORO || "",
// voice channel
vchannelIdForTwo: process.env.DISCORD_VCHANNEL_ID_FOR_TWO || "",
vchannelIdForThree: process.env.DISCORD_VCHANNEL_ID_FOR_THREE || "",
vchannelIdForFour: process.env.DISCORD_VCHANNEL_ID_FOR_FOUR || "",
vchannelIdForGroup: process.env.DISCORD_VCHANNEL_ID_FOR_GROUP || "",
vchannelIdPomodoro25: process.env.DISCORD_VCHANNEL_ID_POMODORO_25_5 || "",
vchannelIdPomodoro50: process.env.DISCORD_VCHANNEL_ID_POMODORO_50_10 || "",
// roles
roleBot: process.env.BOT || "",
roleStudy: process.env.PEOPLE || "",
roleMod: process.env.MOD || "",
roleAdmin: process.env.ADMIN || "",
roleMention: process.env.MENTION || "",
rolesMsg: process.env.ROLES_NOTIFICATION_MSG || "",
rolesMsgTest: process.env.ROLES_MSG_TEST || "",
// other
applicationId: process.env.DISCORD_APPLICATION_ID || "",
token: process.env.DISCORD_TOKEN || "",
botId: process.env.BOT_ID || "",
myId: process.env.MY_ID || "",
enricoId: process.env.ENRICO_ID || "",
},
};

View File

@@ -1,6 +1,7 @@
import type { MessagesServiceInterface } from "entities/messages/messages.service";
import type { ParseKeys } from "i18next";
import type { I18nService } from "lib/i18n/i18n.service";
import { createLogger } from "lib/logger";
import { getRandomInt } from "lib/utils";
export class WaterMeService {
waterLevel: number;
@@ -8,48 +9,45 @@ export class WaterMeService {
private logger = createLogger("WaterMeService");
private thirsty = 3 as const;
private enough = 10 as const;
private full = 10 as const;
messagesService: MessagesServiceInterface;
i18nService: I18nService;
lang: "en" | "de";
constructor(messagesService: MessagesServiceInterface) {
constructor(
messagesService: MessagesServiceInterface,
i18nService: I18nService,
lang: "en" | "de",
) {
this.waterLevel = 0;
this.messagesService = messagesService;
this.i18nService = i18nService;
this.lang = lang;
}
getReply() {
const thirstyReplies = [
"... wow das wars schon??? ich brauche noch mehr wasser :(",
"dankeeeee!!!! ich waer fast verdurstet :(((",
"*roelpssssss*",
];
async getReply() {
// const key = (
// this.waterLevel <= this.thirsty
// ? "water-me.needMoreWater"
// : this.waterLevel <= this.full
// ? "water-me.enoughWater"
// : "water-me.tooMuchWater"
// ) as ParseKeys;
const fullReplies = [
"langsam reicht es :o",
"poah, das hat gut getan",
"das ist krass :3",
];
// return await this.i18nService.t(key, this.lang);
const tooMuchReplies = [
"ES REICHT!!!!",
"bitte hoer auf, ich platze gleich :(",
];
if (this.waterLevel <= this.thirsty) {
return thirstyReplies[getRandomInt(0, thirstyReplies.length - 1)];
}
if (this.waterLevel > this.thirsty && this.waterLevel <= this.enough) {
return fullReplies[getRandomInt(0, fullReplies.length - 1)];
}
if (this.waterLevel > this.enough) {
return tooMuchReplies[getRandomInt(0, tooMuchReplies.length - 1)];
}
if (this.waterLevel <= this.thirsty)
return this.i18nService.t("needMoreWater", this.lang, "waterMe");
if (this.waterLevel <= this.full)
return this.i18nService.t("enoughWater", this.lang, "waterMe");
return this.i18nService.t("tooMuchWater", this.lang, "waterMe");
}
async notifyIfThirsty() {
if (this.waterLevel <= this.thirsty) {
await this.messagesService.sendToChannel(
{ id: "channelId" },
{ content: "ich brauche wasser :(" },
{ content: await this.i18nService.t("waterMe.thirsty", this.lang) },
);
}
}
@@ -66,11 +64,11 @@ export class WaterMeService {
}
async handleCommand(channelId: string) {
const result = this.waterMe();
const result = this.waterMe(); // muss hier await weil promise rueckgabe?
this.messagesService.sendToChannel(
{ id: channelId },
{ content: result.reply },
{ content: await result.reply },
);
}
}

View File

@@ -0,0 +1,64 @@
import i18next, { type ParseKeys } from "i18next";
// import { createLogger } from "lib/logger";
import waterMeDe from "locales/de/water-me";
import waterMeEn from "locales/en/water-me";
export class I18nService {
// private logger = createLogger("I18nService");
private initialized: Promise<void>;
constructor() {
this.initialized = this.init();
// this.logger.debug(`language ${lang}`);
}
randomVariantPlugin = {
type: "postProcessor" as const,
name: "randomVariant",
process(value: string) {
return value;
},
};
async init() {
await i18next.init({
lng: "en",
fallbackLng: "en",
resources: {
en: { waterMe: waterMeEn },
de: { waterMe: waterMeDe },
},
});
}
randomItem<T>(arr: T[]): T {
return arr[Math.floor(Math.random() * arr.length)];
}
async t(
key: ParseKeys,
locale: string,
ns: string,
interpolations?: Record<string, string | number>,
): Promise<string> {
await this.initialized; // wait for init before translating
const fixedT = i18next.getFixedT(
locale.startsWith("de") ? "de" : "en",
ns ?? "waterMe",
);
const value = fixedT(key, { returnObjects: true, ...interpolations });
if (Array.isArray(value)) {
// pick random variant and interpolate manually if needed
const picked = this.randomItem(value as string[]);
// i18next won't interpolate when returnObjects is true, so we do it here
return picked.replace(/\{\{(\w+)\}\}/g, (_, k) =>
interpolations?.[k] !== undefined
? String(interpolations[k])
: `{{${k}}}`,
);
}
return value as unknown as string;
}
}

View File

@@ -0,0 +1,3 @@
import { I18nService } from "lib/i18n/i18n.service";
export const i18nService = new I18nService();

View File

@@ -0,0 +1,10 @@
export default {
needMoreWater: [
"... wow, das wars??? ich brauche noch mehr wasser :(",
"danke!!!! ich bin schon fast verdurstet :(((",
"*roooeeeelps*",
],
enoughWater: ["wow, das hat gut getan", "das ist krass :3"],
tooMuchWater: ["ES REICHT!!!!", "bitte hoer auf, ich platze gleich :("],
thirsty: "ich brauche wasser :c",
} as const;

View File

@@ -0,0 +1,10 @@
export default {
needMoreWater: [
"... wow, thats all??? i need more water :(",
"thank you!!!! i was almost dying of thirst :(((",
"*buuuurrrrp*",
],
enoughWater: ["wow, that felt good", "that's crazy :3"],
tooMuchWater: ["THATS ENOUGH!!!!", "please stop, i'm about to explode :("],
thirsty: "i need some water :c",
} as const;

View File

@@ -0,0 +1,9 @@
import de from "./de";
import en from "./en";
const locales = {
de,
en,
} as const;
export default locales;

View File

@@ -17,11 +17,12 @@
// Best practices
"strict": true,
"skipLibCheck": true,
"strictNullChecks": true,
"noFallthroughCasesInSwitch": true,
// Some stricter flags (disabled by default)
"noUnusedLocals": false,
"noUnusedParameters": false,
"noPropertyAccessFromIndexSignature": false
}
},
}