/
revenore
/
ShopBot
Обзор
Документация
Войти
/
revenore
/
ShopBot
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/utils/localisation.ts
113 строк
4 KB
roulès
Multi language support (#22)
11 ноя 2025, 17:37
Не верифицирован
11 ноя 2025, 17:37
f610ff3
Код
Авторство
О чём код?
import { APIApplicationCommandOption, SlashCommandBuilder } from "discord.js"; import path from 'node:path'; import fs from 'node:fs/promises'; import './strings' import { PrettyLog } from "./pretty-log"; import en_US_locale from '../../locales/en-US.json'; import { getLocale } from ".."; const defaultLocale = en_US_locale export type LocaleStrings = typeof defaultLocale const localsPath = path.join(__dirname, '..', '..','locales'); const locales: { cache: { [code: string]: LocaleStrings }, expired: boolean } = { cache: {}, expired: true }; export async function getLocales() { if (!locales.expired) { return locales.cache } const localesFiles = (await fs.readdir(localsPath)).filter((file) => file.endsWith('.json')) for (const file of localesFiles) { const filePath = path.join(localsPath, file) const localeContent = require(filePath); locales.cache[file.replace('.json', '')] = localeContent } locales.expired = false return locales.cache } export function invalidateLocalesCache() { locales.expired = true } export function getLocaleCodes() { return Object.keys(getLocales()) } export async function addLocalisationToCommand(commandData: SlashCommandBuilder) { const commandDataJSON = commandData.toJSON() commandDataJSON.name_localizations = await getLocaleStrings(['commands', commandDataJSON.name, 'name']) commandDataJSON.description_localizations = await getLocaleStrings(['commands', commandDataJSON.name, 'description']) await addLocalisationToOptions(commandDataJSON.options || [], ['commands', commandDataJSON.name, 'options']) return commandDataJSON } async function addLocalisationToOptions(options: APIApplicationCommandOption[], path: string[]) { for (const option of options) { option.name_localizations = await getLocaleStrings([...path, option.name, 'name'], 32) option.description_localizations = await getLocaleStrings([...path, option.name, 'description'], 100) if ("options" in option && option.options) { await addLocalisationToOptions(option.options, [...path, option.name, 'options']) } } } async function getLocaleStrings(path: string[], maxLength?: number): Promise<{ [key: string]: string | undefined }> { const locales = await getLocales() const result: { [key: string]: string | undefined } = {} for (const localeCode in locales) { const locale = locales[localeCode] as any let current = locale for (const key of path) { current = current[key] if (!current) break } if (typeof current !== 'string') { PrettyLog.warn(`Localisation ${path.join('.')} is not a string in ${localeCode} locale.`) result[localeCode] = undefined continue } if (!current || current.length < 1) { PrettyLog.warn(`Localisation ${path.join('.')} is missing in ${localeCode} locale.`) result[localeCode] = undefined continue } if (maxLength && current.length > maxLength) { current = current.slice(0, maxLength) PrettyLog.warn(`Localisation ${path.join('.')} is longer than ${maxLength} characters in ${localeCode} locale.`) } result[localeCode] = current } return result } export function replaceTemplates(str: string, templates: { [key: string]: string | number }): string { let result = str for (const key in templates) { const value = templates[key] result = result.replace(new RegExp(`{${key}}`, 'g'), String(value)) } return result } export function errorMessages() { return getLocale().errorMessages } export function defaultComponents() { return getLocale().defaultComponents }