diff --git a/module/config.mjs b/module/config.mjs index 37b7adb..61caf63 100644 --- a/module/config.mjs +++ b/module/config.mjs @@ -42,6 +42,11 @@ export const syncMilestones = [ export const syncDice = `1d20`; +export const localizerConfig = { + subKeyPattern: /@(?[a-zA-Z\.]+)/gm, + maxDepth: 10, +}; + export default { stats, statDice, @@ -57,4 +62,5 @@ export default { itemTiers, syncMilestones, syncDice, + localizerConfig }; diff --git a/module/utils/localizer.mjs b/module/utils/localizer.mjs new file mode 100644 index 0000000..147f7c5 --- /dev/null +++ b/module/utils/localizer.mjs @@ -0,0 +1,21 @@ +import { localizerConfig } from "../config.mjs"; + +export function localizer(key, args = {}, depth = 0) { + /** @type {string} */ + let localized = game.i18n.format(key, args); + const subkeys = localized.matchAll(localizerConfig.subKeyPattern); + + // Short-cut to help prevent infinite recursion + if (depth > localizerConfig.maxDepth) { + return localized; + }; + + for (const match of subkeys) { + const subkey = match.groups.key; + localized = + localized.slice(0, match.index) + + localizer(subkey.slice(1), args, depth + 1) + + localized.slice(match.index + subkey.length) + }; + return localized; +}; diff --git a/scripts/preventLocalizationCycles.mjs b/scripts/preventLocalizationCycles.mjs new file mode 100644 index 0000000..0d3b427 --- /dev/null +++ b/scripts/preventLocalizationCycles.mjs @@ -0,0 +1,6 @@ +/* +The purpose of this script is to validate all of the language files to ensure +that there are no cycles in them to prevent infinite recursion. This must pull +the pattern to match subkeys on via the config, otherwise this could result in +inconsistencies with the localizer logic. +*/