diff --git a/src/lib/Vay.ts b/src/lib/Vay.ts index 2741e5a..de60b60 100644 --- a/src/lib/Vay.ts +++ b/src/lib/Vay.ts @@ -95,4 +95,50 @@ export class Vay>> { return this.#currentLanguage; } + translate>(token: K, tData?: TranslationData, language?: ISO639Code) { + const exitWithError = (error: VayError) => { + this.#report(error, { token }); + return token; + }; + const dict = this.#dicts.find(({ locale }) => locale === language || this.#currentLanguage); + + if (!dict) { + return exitWithError(VayError.NO_DICT); + } + + const { phrases } = dict; + const { count, ...data } = tData || {}; + + // Attempt to match the phrase by following the property path. + // If no phrase is found, dispatch an error and return the token. + + const phrase = token.split('.').reduce((entry: any, token: string) => entry[token], phrases); + + if (!phrase) { + return exitWithError(VayError.NO_PHRASE); + } + + if (typeof phrase === 'string') { + return interpolateString(phrase, data); + } + + // If the phrase is an object, all keys should be numerical. + // If this is not the case, the dictionary is malformed or the token is + // incorrect. + + const closestIndex = Object.keys(phrase) + .filter((key) => +key <= getCount(count)) + .pop(); + + if (Object.keys(phrase).some((key) => isNaN(+key)) || closestIndex === undefined) { + return exitWithError(VayError.MALFORMED_PHRASE); + } + + if (typeof phrase[closestIndex] === 'string') { + return interpolateString(phrase[closestIndex], data); + } + + // if no phrase can be matched to the token, return the token + return token; + } }