From 90752ea08abd70af1c349358430ee121b9acdff7 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Tue, 4 Nov 2025 10:09:52 -0400 Subject: language: language.orderStringOptions() / language.$order() --- src/data/things/language.js | 58 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/src/data/things/language.js b/src/data/things/language.js index 43f69f3d..5866027d 100644 --- a/src/data/things/language.js +++ b/src/data/things/language.js @@ -158,6 +158,10 @@ export class Language extends Thing { return this.formatString(...args); } + $order(...args) { + return this.orderStringOptions(...args); + } + assertIntlAvailable(property) { if (!this[property]) { throw new Error(`Intl API ${property} unavailable`); @@ -190,19 +194,14 @@ export class Language extends Thing { const key = this.#joinKeyParts(hasOptions ? args.slice(0, -1) : args); + const template = + this.#getStringTemplateFromFormedKey(key); + const options = (hasOptions ? args.at(-1) : {}); - if (!this.strings) { - throw new Error(`Strings unavailable`); - } - - if (!this.validKeys.includes(key)) { - throw new Error(`Invalid key ${key} accessed`); - } - const constantCasify = name => name .replace(/[A-Z]/g, '_$&') @@ -243,8 +242,7 @@ export class Language extends Thing { ])); const output = this.#iterateOverTemplate({ - template: this.strings[key], - + template, match: languageOptionRegex, insert: ({name: optionName}, canceledForming) => { @@ -324,6 +322,46 @@ export class Language extends Thing { return output; } + orderStringOptions(...args) { + let slice = null, at = null, parts = null; + if (args.length >= 2 && typeof args.at(-1) === 'number') { + if (args.length >= 3 && typeof args.at(-2) === 'number') { + slice = [args.at(-2), args.at(-1)]; + parts = args.slice(0, -2); + } else { + at = args.at(-1); + parts = args.slice(0, -1); + } + } else { + parts = args; + } + + const template = this.getStringTemplate(...parts); + const matches = Array.from(template.matchAll(languageOptionRegex)); + const options = matches.map(({groups}) => groups.name); + + if (slice !== null) return options.slice(...slice); + if (at !== null) return options.at(at); + return options; + } + + getStringTemplate(...args) { + const key = this.#joinKeyParts(args); + return this.#getStringTemplateFromFormedKey(key); + } + + #getStringTemplateFromFormedKey(key) { + if (!this.strings) { + throw new Error(`Strings unavailable`); + } + + if (!this.validKeys.includes(key)) { + throw new Error(`Invalid key ${key} accessed`); + } + + return this.strings[key]; + } + #iterateOverTemplate({ template, match: regexp, -- cgit 1.3.0-6-gf8a5