All files / js-api api.js

100% Statements 97/97
90% Branches 18/20
100% Functions 4/4
100% Lines 97/97

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 981x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 9x 2x 2x 9x 1x 1x 1x 1x 6x 9x 9x 2x 2x 4x 4x 1x 1x 1x 1x 1x 2x 2x 2x 1x 1x 1x 1x 1x 1x 1x 1x 7x 7x 7x 2x 2x 2x 2x 2x 7x 7x 9x 9x 5x 5x 9x 2x 2x 1x 1x 1x 1x 1x 1x 1x 2x 2x 2x 2x 2x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x  
/**
 * This JS API is to allow I18n on canvas elements because all the logic goes to JS
 */
import { getStoresInfoFromElement, setStoreFromElement, isStoreSetOnElement } from '../utils/store-map/store-map.js'
import { queryFromTranslations } from '../utils/translation-query/translation-query.util.js'
import { getLanguageFromElement } from '../utils/algorithms/get-lang-from-element.util.js'
import { loadI18n } from '../html-loader/html-loader.js'
 
/**
 * Translates i18n key
 * @param {string} key - target key
 * @param {Context} [context] - context for translations
 * @returns {Promise<string>} future translated key
 */
export async function translate (key, context) {
  if (!context) {
    return await i18nFromBrowserLanguage(key)
  }
  if ('element' in context && context.element) {
    const { locale, element } = context
    const localeStr = locale || getLanguageFromElement(element)
    return await i18nFromElementAndLocale(key, element, localeStr)
  }
  const { locale } = context
  const localeStr = locale || getLanguageFromElement(document.documentElement)
  if ('store' in context && context.store) {
    return await i18nFromStoreAndLocale(key, context.store, localeStr)
  }
  return await i18nFromElementAndLocale(key, document.documentElement, localeStr)
}
 
/**
 * @param {string} key - target key
 * @returns {Promise<string>} future translated key
 */
async function i18nFromBrowserLanguage (key) {
  return await i18nFromElementAndLocale(key, document.documentElement, getLanguageFromElement(document.documentElement))
}
 
/**
 *
 * @param {string} key - target key
 * @param {Element} element - target element
 * @param {string | Intl.Locale} localeString - target language to translate
 * @returns {Promise<string>} future translated key
 */
async function i18nFromElementAndLocale (key, element, localeString) {
  const locale = new Intl.Locale(localeString)
  if (element?.ownerDocument?.documentElement && !isStoreSetOnElement(element.ownerDocument.documentElement)) {
    const window = document.defaultView
    if (!window) { return key }
    const store = await loadI18n(window)
    setStoreFromElement(document.documentElement, store)
  }
 
  for (const storeInfo of getStoresInfoFromElement(element)) {
    const result = queryFromTranslations(key, await storeInfo.store.translationsFromLanguage(locale))
    if (result.found) {
      return result.translate(locale)
    }
  }
  return key
}
 
/**
 * @param {string} key - target key
 * @param {import("../utils/store/translation-store.js").TranslationStore} store - target store
 * @param {string | Intl.Locale} localeString - target language to translate
 * @returns {Promise<string>} future translated key
 */
async function i18nFromStoreAndLocale (key, store, localeString) {
  const locale = new Intl.Locale(localeString)
  const result = queryFromTranslations(key, await store.translationsFromLanguage(locale))
  return result.found ? result.translate(locale) : key
}
 
/** @typedef {DOMContext| StoreContext | LocaleContext} Context */
 
/**
 * @typedef {object} DOMContext
 * Translate based on information of an DOM element
 * @property {Element} element - target element
 * @property {string | Intl.Locale} [locale] - target language to translate, finds the language from element if not defined
 */
 
/**
 * @typedef {object} StoreContext
 * Translate based on a store
 * @property {import("../utils/store/translation-store.js").TranslationStore} store - target store
 * @property {string | Intl.Locale} [locale] - target language to translate, finds the language from DOM document if not defined
 */
 
/**
 * @typedef {object} LocaleContext
 * Translate based on initially loaded i8n data in the window
 * @property {string | Intl.Locale} [locale] - target language to translate, finds the language from DOM document if not defined
 */