2023-08-27 22:20:43 +02:00
import { registerDebugFunction } from "./power-user.js" ;
2023-08-22 09:37:18 +02:00
import { waitUntilCondition } from "./utils.js" ;
const storageKey = "language" ;
export const localeData = await fetch ( "i18n.json" ) . then ( response => response . json ( ) ) ;
2023-08-24 14:13:04 +02:00
function getMissingTranslations ( ) {
const missingData = [ ] ;
for ( const language of localeData . lang ) {
$ ( document ) . find ( "[data-i18n]" ) . each ( function ( ) {
const keys = $ ( this ) . data ( "i18n" ) . split ( ';' ) ; // Multi-key entries are ; delimited
for ( const key of keys ) {
const attributeMatch = key . match ( /\[(\S+)\](.+)/ ) ; // [attribute]key
if ( attributeMatch ) { // attribute-tagged key
const localizedValue = localeData ? . [ language ] ? . [ attributeMatch [ 2 ] ] ;
if ( ! localizedValue ) {
missingData . push ( { key , language , value : $ ( this ) . attr ( attributeMatch [ 1 ] ) } ) ;
}
} else { // No attribute tag, treat as 'text'
const localizedValue = localeData ? . [ language ] ? . [ key ] ;
if ( ! localizedValue ) {
missingData . push ( { key , language , value : $ ( this ) . text ( ) . trim ( ) } ) ;
}
}
}
} ) ;
}
// Remove duplicates
const uniqueMissingData = [ ] ;
for ( const { key , language , value } of missingData ) {
if ( ! uniqueMissingData . some ( x => x . key === key && x . language === language && x . value === value ) ) {
uniqueMissingData . push ( { key , language , value } ) ;
}
}
// Sort by language, then key
uniqueMissingData . sort ( ( a , b ) => a . language . localeCompare ( b . language ) || a . key . localeCompare ( b . key ) ) ;
// Map to { language: { key: value } }
const missingDataMap = { } ;
for ( const { key , language , value } of uniqueMissingData ) {
if ( ! missingDataMap [ language ] ) {
missingDataMap [ language ] = { } ;
}
missingDataMap [ language ] [ key ] = value ;
}
console . table ( uniqueMissingData ) ;
console . log ( missingDataMap ) ;
2023-08-27 22:20:43 +02:00
toastr . success ( ` Found ${ uniqueMissingData . length } missing translations. See browser console for details. ` ) ;
}
2023-08-24 14:13:04 +02:00
2023-08-22 09:37:18 +02:00
export function applyLocale ( root = document ) {
const overrideLanguage = localStorage . getItem ( "language" ) ;
var language = overrideLanguage || navigator . language || navigator . userLanguage ;
language = language . toLowerCase ( ) ;
//load the appropriate language file
if ( localeData . lang . indexOf ( language ) < 0 ) language = "en" ;
const $root = root instanceof Document ? $ ( root ) : $ ( new DOMParser ( ) . parseFromString ( root , "text/html" ) ) ;
//find all the elements with `data-i18n` attribute
$root . find ( "[data-i18n]" ) . each ( function ( ) {
//read the translation from the language data
const keys = $ ( this ) . data ( "i18n" ) . split ( ';' ) ; // Multi-key entries are ; delimited
for ( const key of keys ) {
const attributeMatch = key . match ( /\[(\S+)\](.+)/ ) ; // [attribute]key
if ( attributeMatch ) { // attribute-tagged key
const localizedValue = localeData ? . [ language ] ? . [ attributeMatch [ 2 ] ] ;
if ( localizedValue ) {
$ ( this ) . attr ( attributeMatch [ 1 ] , localizedValue ) ;
}
} else { // No attribute tag, treat as 'text'
const localizedValue = localeData ? . [ language ] ? . [ key ] ;
if ( localizedValue ) {
$ ( this ) . text ( localizedValue ) ;
}
}
}
} ) ;
if ( root !== document ) {
return $root . get ( 0 ) . body . innerHTML ;
}
}
function addLanguagesToDropdown ( ) {
if ( ! Array . isArray ( localeData ? . lang ) ) {
return ;
}
for ( const lang of localeData . lang ) {
const option = document . createElement ( 'option' ) ;
option . value = lang ;
option . innerText = lang ;
$ ( '#ui_language_select' ) . append ( option ) ;
}
const selectedLanguage = localStorage . getItem ( storageKey ) ;
if ( selectedLanguage ) {
$ ( '#ui_language_select' ) . val ( selectedLanguage ) ;
}
}
jQuery ( async ( ) => {
waitUntilCondition ( ( ) => ! ! localeData ) ;
applyLocale ( ) ;
addLanguagesToDropdown ( ) ;
$ ( '#ui_language_select' ) . on ( 'change' , async function ( ) {
2023-08-22 13:30:49 +02:00
const language = String ( $ ( this ) . val ( ) ) ;
2023-08-22 09:37:18 +02:00
if ( language ) {
localStorage . setItem ( storageKey , language ) ;
} else {
localStorage . removeItem ( storageKey ) ;
}
location . reload ( ) ;
} ) ;
2023-08-27 22:20:43 +02:00
registerDebugFunction ( 'getMissingTranslations' , 'Get missing translations' , 'Detects missing localization data and dumps the data into the browser console.' , getMissingTranslations ) ;
registerDebugFunction ( 'applyLocale' , 'Apply locale' , 'Reapplies the currently selected locale to the page.' , applyLocale ) ;
2023-08-22 09:37:18 +02:00
} ) ;