feat: internationalization service

This commit is contained in:
Slincnik 2024-12-12 13:01:59 +03:00
parent bce6242e1e
commit 62ab9250fc
No known key found for this signature in database
259 changed files with 77 additions and 7 deletions

View file

@ -1,5 +1,5 @@
import { model, Schema } from "mongoose"; import { model, Schema } from "mongoose";
import { langs } from "../languages/language-meta.js"; import { client } from "../index.js";
export default model( export default model(
"Guild", "Guild",
@ -9,7 +9,7 @@ export default model(
membersData: { type: Object, default: {} }, membersData: { type: Object, default: {} },
members: [{ type: Schema.Types.ObjectId, ref: "Member" }], members: [{ type: Schema.Types.ObjectId, ref: "Member" }],
language: { type: String, default: langs.find(l => l.default).name }, language: { type: String, default: client.configService.get("defaultLang") },
plugins: { plugins: {
type: Object, type: Object,
default: { default: {

View file

@ -0,0 +1,71 @@
import i18next from "i18next";
import Backend from "i18next-fs-backend";
import fs from "fs/promises";
import { resolve, join } from "path";
import logger from "../../helpers/logger.js";
import supportedLanguages from "./language-meta.js";
export default class InternationalizationService {
/**
* Constructs an instance of the InternationalizationService.
*
* @param {import("../../index.js").client} client - The client instance.
* @param {Object} [options={}] - Optional configuration options.
*/
constructor(client, options = {}) {
this.client = client;
this.options = {
localesPath: resolve(this.client.configService.get("paths.locales")),
defaultLanguage: options.defaultLanguage || "en-US",
};
this.i18next = this.#init();
}
get getSupportedLanguages() {
return supportedLanguages.map(lang => lang.locale);
}
async #walkDirectory(dir, namespaces = [], folderName = "") {
const files = await fs.readdir(dir, { withFileTypes: true });
const languages = [];
for (const file of files) {
if (file.isDirectory()) {
const isLanguage = file.name.includes("-");
if (isLanguage) languages.push(file.name);
const folder = await this.#walkDirectory(join(dir, file.name), namespaces, isLanguage ? "" : `${file.name}/`);
namespaces = folder.namespaces;
} else {
namespaces.push(`${folderName}${file.name.substr(0, file.name.length - 5)}`);
}
}
return { namespaces: [...new Set(namespaces)], languages };
}
async #init() {
const { namespaces, languages } = await this.#walkDirectory(this.options.localesPath);
const i18n = await i18next.use(Backend).init({
backend: {
loadPath: resolve(this.options.localesPath, "./{{lng}}/{{ns}}.json"),
},
debug: this.client.configService.get("production") ? true : false,
fallbackLng: this.options.defaultLanguage,
preload: languages,
ns: namespaces,
defaultNS: namespaces[0],
initImmediate: false,
});
this.client.translate = (key, options = {}) => {
const lng = options.lng || this.options.defaultLanguage;
return i18next.t(key, { lng, ...options });
};
logger.log("Internationalization initialized");
return i18n;
}
}

View file

@ -4,20 +4,17 @@ export default [
nativeName: "English", nativeName: "English",
locale: "en-US", locale: "en-US",
format: "HH:mm:ss, MMMM Do YYYY", format: "HH:mm:ss, MMMM Do YYYY",
default: true,
}, },
{ {
name: "ru-RU", name: "ru-RU",
nativeName: "Русский", nativeName: "Русский",
locale: "ru-RU", locale: "ru-RU",
format: "HH:mm:ss, Do MMMM YYYY", format: "HH:mm:ss, Do MMMM YYYY",
default: false,
}, },
{ {
name: "uk-UA", name: "uk-UA",
nativeName: "Українська", nativeName: "Українська",
locale: "uk-UA", locale: "uk-UA",
format: "HH:mm:ss, Do MMMM YYYY", format: "HH:mm:ss, Do MMMM YYYY",
default: false,
}, },
]; ];

Some files were not shown because too many files have changed in this diff Show more