All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 3m43s
163 lines
5.4 KiB
TypeScript
163 lines
5.4 KiB
TypeScript
import type { Locale } from "discord.js"
|
|
import frLocale from "@/locales/fr.json"
|
|
import enLocale from "@/locales/en.json"
|
|
import dbGuild from "@/schemas/guild"
|
|
import { logConsoleError } from "./console"
|
|
|
|
// Variables d'environnement pour les locales avec valeurs par défaut
|
|
const DEFAULT_LOCALE = process.env.DEFAULT_LOCALE ?? 'fr'
|
|
const CONSOLE_LOCALE = process.env.CONSOLE_LOCALE ?? 'en'
|
|
|
|
// Types pour l'internationalisation
|
|
type LocaleData = Record<string, unknown>
|
|
type ReplacementParams = Record<string, string | number>
|
|
type TranslationKey = string
|
|
|
|
/**
|
|
* Récupère la locale configurée pour un serveur
|
|
* @param guildId - L'ID du serveur Discord
|
|
* @returns La locale configurée ou 'fr' par défaut
|
|
*/
|
|
export async function getGuildLocale(guildId: string): Promise<string> {
|
|
try {
|
|
const guildProfile = await dbGuild.findOne({ guildId })
|
|
return guildProfile?.guildLocale ?? 'fr'
|
|
} catch (error) {
|
|
logConsoleError('mongoose', 'locale.fetch_error', { guildId }, error as Error)
|
|
return 'fr'
|
|
}
|
|
}
|
|
|
|
// Conversion des imports en type LocaleData
|
|
const frLocaleData = frLocale as unknown as LocaleData
|
|
const enLocaleData = enLocale as unknown as LocaleData
|
|
|
|
// Locales supportées
|
|
const locales = {
|
|
'fr': frLocaleData,
|
|
'en-US': enLocaleData,
|
|
'en-GB': enLocaleData
|
|
} as const
|
|
|
|
type SupportedLocale = keyof typeof locales
|
|
|
|
/**
|
|
* Récupère une traduction basée sur la locale et la clé
|
|
*/
|
|
function getNestedValue(obj: LocaleData, path: string): string | undefined {
|
|
try {
|
|
const keys = path.split('.')
|
|
let current: unknown = obj
|
|
|
|
for (const key of keys) {
|
|
if (current !== null && typeof current === 'object' && key in current) current = (current as Record<string, unknown>)[key]
|
|
else return undefined
|
|
}
|
|
|
|
return typeof current === 'string' ? current : undefined
|
|
} catch { return undefined }
|
|
}
|
|
|
|
/**
|
|
* Remplace les paramètres dans une chaîne de caractères
|
|
* Exemple: "Hello {name}" avec {name: "World"} devient "Hello World"
|
|
*/
|
|
function replaceParams(text: string, params: ReplacementParams = {}): string {
|
|
return text.replace(/\{(\w+)\}/g, (match, key: string) => {
|
|
if (Object.prototype.hasOwnProperty.call(params, key)) return params[key].toString()
|
|
return match
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Fonction principale de localisation
|
|
* @param locale - La locale Discord de l'utilisateur
|
|
* @param key - La clé de traduction (ex: "player.not_in_voice")
|
|
* @param params - Les paramètres à remplacer dans la traduction
|
|
* @returns La chaîne traduite
|
|
*/
|
|
export function t(locale: Locale | string, key: TranslationKey, params: ReplacementParams = {}): string {
|
|
// Détermine la locale à utiliser (par défaut de la config)
|
|
const supportedLocale: SupportedLocale = (Object.keys(locales).includes(locale)) ? locale as SupportedLocale : DEFAULT_LOCALE as SupportedLocale
|
|
|
|
// Récupère les données de locale
|
|
const localeData = locales[supportedLocale]
|
|
|
|
// Récupère la traduction
|
|
const translation = getNestedValue(localeData, key)
|
|
|
|
if (!translation) {
|
|
console.warn(`[Localization] Translation not found for key: ${key} in locale: ${supportedLocale}`)
|
|
return key // Retourne la clé si la traduction n'est pas trouvée
|
|
}
|
|
|
|
// Remplace les paramètres et retourne la traduction
|
|
return replaceParams(translation, params)
|
|
}
|
|
|
|
/**
|
|
* Fonction helper pour obtenir la locale française par défaut
|
|
*/
|
|
export function fr(key: TranslationKey, params: ReplacementParams = {}): string {
|
|
return t('fr', key, params)
|
|
}
|
|
|
|
/**
|
|
* Fonction helper pour obtenir la locale anglaise
|
|
*/
|
|
export function en(key: TranslationKey, params: ReplacementParams = {}): string {
|
|
return t('en-US', key, params)
|
|
}
|
|
|
|
/**
|
|
* Obtient les locales supportées pour une commande
|
|
* Utilisé pour les localisations des commandes slash
|
|
*/
|
|
export function getCommandLocalizations(baseKey: string) {
|
|
return {
|
|
fr: getNestedValue(frLocaleData, baseKey) ?? baseKey,
|
|
'en-US': getNestedValue(enLocaleData, baseKey) ?? baseKey,
|
|
'en-GB': getNestedValue(enLocaleData, baseKey) ?? baseKey
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fonction de localisation utilisant la locale du serveur
|
|
* @param guildLocale - La locale configurée du serveur
|
|
* @param key - La clé de traduction (ex: "player.not_in_voice")
|
|
* @param params - Les paramètres à remplacer dans la traduction
|
|
* @returns La chaîne traduite
|
|
*/
|
|
export function tGuild(guildLocale: string, key: TranslationKey, params: ReplacementParams = {}): string {
|
|
return t(guildLocale, key, params)
|
|
}
|
|
|
|
/**
|
|
* Fonction helper pour obtenir la locale appropriée (serveur ou utilisateur)
|
|
* @param guildId - L'ID du serveur (optionnel)
|
|
* @param userLocale - La locale de l'utilisateur
|
|
* @returns La locale à utiliser
|
|
*/
|
|
export async function getLocaleForContext(guildId: string | null, userLocale: string): Promise<string> {
|
|
if (guildId) return await getGuildLocale(guildId)
|
|
return userLocale
|
|
}
|
|
|
|
/**
|
|
* Fonction de traduction intelligente qui utilise automatiquement la locale du serveur
|
|
* @param interaction - L'interaction Discord
|
|
* @param key - La clé de traduction
|
|
* @param params - Les paramètres de remplacement
|
|
* @returns La chaîne traduite
|
|
*/
|
|
export async function tSmart(interaction: { guild: { id: string } | null; locale: string }, key: TranslationKey, params: ReplacementParams = {}): Promise<string> {
|
|
const locale = await getLocaleForContext(interaction.guild?.id ?? null, interaction.locale)
|
|
return t(locale, key, params)
|
|
}
|
|
|
|
// Export des constantes de locale
|
|
export { DEFAULT_LOCALE, CONSOLE_LOCALE }
|
|
|
|
// Export des types pour utilisation externe
|
|
export type { TranslationKey, ReplacementParams, SupportedLocale }
|