All files / utils/algorithms get-lang-from-element.util.js

91.07% Statements 51/56
77.77% Branches 14/18
100% Functions 3/3
91.07% Lines 51/56

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 571x 1x 1x 1x 1x 1x 2x 2x 2x       2x 2x 2x 1x 1x 1x 1x 1x 1x 5x 5x 1x 5x 2x 2x 2x 2x 1x 1x 1x 1x 1x 1x 1x 300x     300x 745x 745x 299x 299x 299x 745x 288x 288x 6x 745x 5x 5x 745x 1x 1x 1x  
import { traverseUpDomWithSlots } from './traverse-up-dom.js'
 
/**
 * @param {Element} element - target element
 * @returns {string} fallback language
 */
function getFallbackLanguage (element) {
  const root = element.ownerDocument.defaultView ?? globalThis
  if (!root.navigator) {
    // OS/node/browser independent way of obtaining the default locale
    return Intl.DateTimeFormat().resolvedOptions().locale
  }
  const langs = root.navigator.languages || [root.navigator.language]
  return langs[0]
}
 
/**
 * @param {Element} element - element with invalid lang attribute
 * @param {string} invalidLanguage - the invalid language detected
 * @returns {string} corrected language
 */
function handleInvalidLanguage (element, invalidLanguage) {
  if (element === element.ownerDocument.documentElement) {
    return getFallbackLanguage(element)
  } else if (element.parentNode instanceof ShadowRoot) {
    return getLanguageFromElement(element.parentNode.host)
  }
  return getLanguageFromElement(element.parentElement)
}
 
/**
 * Gets the currently applied language of element, get default locale otherwise
 * @param {Element | null} element - target element
 * @returns {string} element language
 */
export function getLanguageFromElement (element) {
  if (element == null) {
    return Intl.DateTimeFormat().resolvedOptions().locale
  }
  for (const node of traverseUpDomWithSlots(element)) {
    const langValue = node.getAttribute('lang')
    if (!langValue) continue
    try {
      const locale = new Intl.Locale(langValue)
      const { language, region } = locale
      if (region == null) {
        return language
      }
      return `${language}-${region}`
    } catch {
      return handleInvalidLanguage(node, langValue)
    }
  }
 
  return getFallbackLanguage(element)
}