UNPKG

senselogic-lingo

Version:

Text localization and processing.

1,068 lines (924 loc) 24 kB
// -- CONSTANTS const valueExpression = /^(.*?)([<=>]+)(.*)$/; // -- VARIABLES export let textBySlugMap = new Map(), languageSeparator = '\n¨', languageTag = 'en', continentCode = '', countryCode = '', languageCode = 'en', defaultLanguageCode = 'en', substitutionPrefix = '{', substitutionSuffix = '}'; // -- FUNCTIONS export function setTextBySlug( text, textSlug ) { textBySlugMap.set( textSlug, text ); } // ~~ export function getTextBySlug( textSlug ) { if ( textBySlugMap.has( textSlug ) ) { return textBySlugMap.get( textSlug ); } else { logWarning( 'Missing text slug : ' + textSlug ); return ''; } } // ~~ export function getContinentCodeFromCountryCode( countryCode ) { switch ( countryCode ) { case 'AF' : return 'AS'; case 'AX' : return 'EU'; case 'AL' : return 'EU'; case 'DZ' : return 'AF'; case 'AS' : return 'OC'; case 'AD' : return 'EU'; case 'AO' : return 'AF'; case 'AI' : return 'CA'; case 'AQ' : return 'AN'; case 'AG' : return 'CA'; case 'AR' : return 'SA'; case 'AM' : return 'EU'; case 'AW' : return 'CA'; case 'AU' : return 'OC'; case 'AT' : return 'EU'; case 'AZ' : return 'EU'; case 'BS' : return 'CA'; case 'BH' : return 'AS'; case 'BD' : return 'AS'; case 'BB' : return 'CA'; case 'BY' : return 'EU'; case 'BE' : return 'EU'; case 'BZ' : return 'CA'; case 'BJ' : return 'AF'; case 'BM' : return 'CA'; case 'BT' : return 'AS'; case 'BO' : return 'SA'; case 'BA' : return 'EU'; case 'BW' : return 'AF'; case 'BR' : return 'SA'; case 'IO' : return 'AF'; case 'VG' : return 'CA'; case 'BN' : return 'AS'; case 'BG' : return 'EU'; case 'BF' : return 'AF'; case 'BI' : return 'AF'; case 'KH' : return 'AS'; case 'CM' : return 'AF'; case 'CA' : return 'NA'; case 'CV' : return 'AF'; case 'KY' : return 'CA'; case 'CF' : return 'AF'; case 'TD' : return 'AF'; case 'CL' : return 'SA'; case 'CN' : return 'AS'; case 'CX' : return 'OC'; case 'CC' : return 'OC'; case 'CO' : return 'SA'; case 'KM' : return 'AF'; case 'CK' : return 'OC'; case 'CR' : return 'CA'; case 'CI' : return 'AF'; case 'HR' : return 'EU'; case 'CU' : return 'CA'; case 'CW' : return 'CA'; case 'CY' : return 'EU'; case 'CZ' : return 'EU'; case 'CD' : return 'AF'; case 'DK' : return 'EU'; case 'DJ' : return 'AF'; case 'DM' : return 'CA'; case 'DO' : return 'CA'; case 'EC' : return 'SA'; case 'EG' : return 'AF'; case 'SV' : return 'CA'; case 'GQ' : return 'AF'; case 'ER' : return 'AF'; case 'EE' : return 'EU'; case 'ET' : return 'AF'; case 'FK' : return 'SA'; case 'FO' : return 'EU'; case 'FM' : return 'OC'; case 'FJ' : return 'OC'; case 'FI' : return 'EU'; case 'FR' : return 'EU'; case 'PF' : return 'OC'; case 'TF' : return 'AN'; case 'GA' : return 'AF'; case 'GE' : return 'EU'; case 'DE' : return 'EU'; case 'GH' : return 'AF'; case 'GI' : return 'EU'; case 'GR' : return 'EU'; case 'GL' : return 'CA'; case 'GD' : return 'CA'; case 'GU' : return 'OC'; case 'GT' : return 'CA'; case 'GG' : return 'EU'; case 'GN' : return 'AF'; case 'GW' : return 'AF'; case 'GY' : return 'SA'; case 'HT' : return 'CA'; case 'HM' : return 'AN'; case 'HN' : return 'CA'; case 'HK' : return 'AS'; case 'HU' : return 'EU'; case 'IS' : return 'EU'; case 'IN' : return 'AS'; case 'ID' : return 'AS'; case 'IR' : return 'AS'; case 'IQ' : return 'AS'; case 'IE' : return 'EU'; case 'IM' : return 'EU'; case 'IL' : return 'AS'; case 'IT' : return 'EU'; case 'JM' : return 'CA'; case 'JP' : return 'AS'; case 'JE' : return 'EU'; case 'JO' : return 'AS'; case 'KZ' : return 'AS'; case 'KE' : return 'AF'; case 'KI' : return 'OC'; case 'KO' : return 'EU'; case 'KW' : return 'AS'; case 'KG' : return 'AS'; case 'LA' : return 'AS'; case 'LV' : return 'EU'; case 'LB' : return 'AS'; case 'LS' : return 'AF'; case 'LR' : return 'AF'; case 'LY' : return 'AF'; case 'LI' : return 'EU'; case 'LT' : return 'EU'; case 'LU' : return 'EU'; case 'MO' : return 'AS'; case 'MK' : return 'EU'; case 'MG' : return 'AF'; case 'MW' : return 'AF'; case 'MY' : return 'AS'; case 'MV' : return 'AS'; case 'ML' : return 'AF'; case 'MT' : return 'EU'; case 'MH' : return 'OC'; case 'MR' : return 'AF'; case 'MU' : return 'AF'; case 'MX' : return 'CA'; case 'MD' : return 'EU'; case 'MC' : return 'EU'; case 'MN' : return 'AS'; case 'ME' : return 'EU'; case 'MS' : return 'CA'; case 'MA' : return 'AF'; case 'MZ' : return 'AF'; case 'MM' : return 'AS'; case 'NA' : return 'AF'; case 'NR' : return 'OC'; case 'NP' : return 'AS'; case 'NL' : return 'EU'; case 'NC' : return 'OC'; case 'NZ' : return 'OC'; case 'NI' : return 'CA'; case 'NE' : return 'AF'; case 'NG' : return 'AF'; case 'NU' : return 'OC'; case 'NF' : return 'OC'; case 'KP' : return 'AS'; case 'MP' : return 'OC'; case 'NO' : return 'EU'; case 'OM' : return 'AS'; case 'PK' : return 'AS'; case 'PW' : return 'OC'; case 'PS' : return 'AS'; case 'PA' : return 'CA'; case 'PG' : return 'OC'; case 'PY' : return 'SA'; case 'PE' : return 'SA'; case 'PH' : return 'AS'; case 'PN' : return 'OC'; case 'PL' : return 'EU'; case 'PT' : return 'EU'; case 'PR' : return 'CA'; case 'QA' : return 'AS'; case 'CG' : return 'AF'; case 'RO' : return 'EU'; case 'RU' : return 'EU'; case 'RW' : return 'AF'; case 'BL' : return 'CA'; case 'SH' : return 'AF'; case 'KN' : return 'CA'; case 'LC' : return 'CA'; case 'MF' : return 'CA'; case 'PM' : return 'CA'; case 'VC' : return 'CA'; case 'WS' : return 'OC'; case 'SM' : return 'EU'; case 'ST' : return 'AF'; case 'SA' : return 'AS'; case 'SN' : return 'AF'; case 'RS' : return 'EU'; case 'SC' : return 'AF'; case 'SL' : return 'AF'; case 'SG' : return 'AS'; case 'SX' : return 'CA'; case 'SK' : return 'EU'; case 'SI' : return 'EU'; case 'SB' : return 'OC'; case 'SO' : return 'AF'; case 'ZA' : return 'AF'; case 'GS' : return 'AN'; case 'KR' : return 'AS'; case 'SS' : return 'AF'; case 'ES' : return 'EU'; case 'LK' : return 'AS'; case 'SD' : return 'AF'; case 'SR' : return 'SA'; case 'SJ' : return 'EU'; case 'SZ' : return 'AF'; case 'SE' : return 'EU'; case 'CH' : return 'EU'; case 'SY' : return 'AS'; case 'TW' : return 'AS'; case 'TJ' : return 'AS'; case 'TZ' : return 'AF'; case 'TH' : return 'AS'; case 'GM' : return 'AF'; case 'TL' : return 'AS'; case 'TG' : return 'AF'; case 'TK' : return 'OC'; case 'TO' : return 'OC'; case 'TT' : return 'CA'; case 'TN' : return 'AF'; case 'TR' : return 'EU'; case 'TM' : return 'AS'; case 'TC' : return 'CA'; case 'TV' : return 'OC'; case 'UG' : return 'AF'; case 'UA' : return 'EU'; case 'AE' : return 'AS'; case 'GB' : return 'EU'; case 'US' : return 'NA'; case 'UY' : return 'SA'; case 'UM' : return 'OC'; case 'VI' : return 'CA'; case 'UZ' : return 'AS'; case 'VU' : return 'OC'; case 'VA' : return 'EU'; case 'VE' : return 'SA'; case 'VN' : return 'AS'; case 'WF' : return 'OC'; case 'EH' : return 'AF'; case 'YE' : return 'AS'; case 'ZM' : return 'AF'; case 'ZW' : return 'AF'; } return ''; } // ~~ export function getContinentSlugFromContinentCode( continentCode ) { switch ( continentCode ) { case 'AF' : return 'africa'; case 'AN' : return 'antarctica'; case 'AS' : return 'asia'; case 'OC' : return 'oceania'; case 'CA' : return 'central-america'; case 'EU' : return 'europe'; case 'NA' : return 'north-america'; case 'SA' : return 'south-america'; } return ''; } // ~~ export function setLanguageSeparator( languageSeparator_ ) { languageSeparator = languageSeparator_; } // ~~ export function getLanguageSeparator( ) { return languageSeparator; } // ~~ export function setLanguageTag( languageTag_ ) { languageTag = languageTag_; } // ~~ export function getLanguageTag( ) { return languageTag; } // ~~ export function updateLanguageTag( ) { languageTag = getTrimmedLanguageTag( languageCode + '-' + countryCode + '-' + continentCode ); } // ~~ export function setContinentCode( continentCode_ ) { continentCode = continentCode_; updateLanguageTag(); } // ~~ export function getContinentCode( ) { return continentCode; } // ~~ export function setCountryCode( countryCode_ ) { countryCode = countryCode_; setContinentCode( getContinentCodeFromCountryCode( countryCode_ ) ); } // ~~ export function getCountryCode( ) { return countryCode; } // ~~ export function setLanguageCode( languageCode_ ) { languageCode = languageCode_; updateLanguageTag(); } // ~~ export function getLanguageCode( ) { return languageCode; } // ~~ export function setDefaultLanguageCode( defaultLanguageCode_ ) { defaultLanguageCode = defaultLanguageCode_; } // ~~ export function getDefaultLanguageCode( ) { return defaultLanguageCode; } // ~~ export function setSubstitutionPrefix( substitutionPrefix_ ) { substitutionPrefix = substitutionPrefix_; } // ~~ export function getSubstitutionPrefix( ) { return substitutionPrefix; } // ~~ export function setSubstitutionSuffix( substitutionSuffix_ ) { substitutionSuffix = substitutionSuffix_; } // ~~ export function getSubstitutionSuffix( ) { return substitutionSuffix; } // ~~ export function getFormattedNumberText( number, style = undefined, currency = undefined ) { let numberFormat; if ( style === 'currency' ) { numberFormat = new Intl.NumberFormat( languageTag, { style, currency } ); } else { numberFormat = new Intl.NumberFormat( languageTag, { style } ); } return numberFormat.format( number ); } // ~~ export function getFormattedDateText( date, style = undefined, timeZone = undefined, yearFormat = undefined, monthFormat = undefined, dayFormat = undefined, weekdayFormat = undefined ) { let dateTimeFormat = new Intl.DateTimeFormat( languageTag, { dateStyle : style, year: yearFormat, month: monthFormat, day: dayFormat, weekday: weekdayFormat, timeZone } ); return dateTimeFormat.format( date ); } // ~~ export function getFormattedTimeText( time, style = undefined, timeZone = undefined, hourFormat = undefined, minuteFormat = undefined, secondFormat = undefined ) { let dateTimeFormat = new Intl.DateTimeFormat( languageTag, { timeStyle : style, hour: hourFormat, minute: minuteFormat, second: secondFormat, timeZone } ); return dateTimeFormat.format( time ); } // ~~ export function getFormattedCountryName( countryCode ) { let displayNames = new Intl.DisplayNames( [ languageTag ], { type: 'region' } ); return displayNames.of( countryCode ); } // ~~ export function getFormattedLanguageName( languageCode ) { let displayNames = new Intl.DisplayNames( [ languageTag ], { type: 'language' } ); return displayNames.of( languageCode ); } // ~~ export function getFormattedCurrencyName( currencyCode ) { let displayNames = new Intl.DisplayNames( [ languageTag ], { type: 'currency' } ); return displayNames.of( currencyCode ); } // ~~ export function getFormattedArrayText( elementArray, style = undefined, type = undefined ) { let listFormat = new Intl.ListFormat( languageTag, { style, type } ); return listFormat.format( elementArray ); } // ~~ export function getBrowserLanguageCode( browserLanguageText, validLanguageCodeArray, defaultLanguageCode = '' ) { let browserLanguageArray = browserLanguageText.toLowerCase().split( ',' ); for ( let browserLanguage of browserLanguageArray ) { let browserLanguageCode = browserLanguage.slice( 0, 2 ); if ( validLanguageCodeArray.indexOf( browserLanguageCode ) >= 0 ) { return browserLanguageCode; } } return defaultLanguageCode; } // ~~ export function getTrimmedLanguageTag( languageTag ) { if ( languageTag.endsWith( '--' ) ) { return languageTag.slice( 0, -2 ); } else if ( languageTag.endsWith( '-' ) ) { return languageTag.slice( 0, -1 ); } else { return languageTag; } } // ~~ export function getUntranslatedText( multilingualText ) { return multilingualText.split( languageSeparator )[ 0 ]; } // ~~ export function matchesLanguageSpecifier( languageSpecifier, languageTag ) { let languageTagPartArray = ( languageTag + '--' ).split( '-' ); for ( let languageSpecifierTag of languageSpecifier.split( ',' ) ) { let languageSpecifierTagPartArray = ( languageSpecifierTag + '--' ).split( '-' ); if ( ( languageTagPartArray[ 0 ] === '' || languageSpecifierTagPartArray[ 0 ] === '' || languageTagPartArray[ 0 ] === languageSpecifierTagPartArray[ 0 ] ) && ( languageTagPartArray[ 1 ] === '' || languageSpecifierTagPartArray[ 1 ] === '' || languageTagPartArray[ 1 ] === languageSpecifierTagPartArray[ 1 ] ) && ( languageTagPartArray[ 2 ] === '' || languageSpecifierTagPartArray[ 2 ] === '' || languageTagPartArray[ 2 ] === languageSpecifierTagPartArray[ 2 ] ) ) { return true; } } return false; } // ~~ export function matchesValueSpecifier( valueSpecifier, valueByNameMap ) { if ( valueByNameMap !== undefined ) { let match = valueSpecifier.match( valueExpression ); if ( match ) { let valueName = match[ 1 ]; let operator = match[ 2 ]; let otherValue = match[ 3 ]; if ( valueByNameMap !== undefined && valueName in valueByNameMap ) { let value = valueByNameMap[ valueName ]; if ( typeof value === 'number' ) { otherValue = Number( otherValue ); } if ( ( operator === '=' && value === otherValue ) || ( operator === '<' && value < otherValue ) || ( operator === '<=' && value <= otherValue ) || ( operator === '>=' && value >= otherValue ) || ( operator === '>' && value > otherValue ) || ( operator === '<>' && value !== otherValue ) ) { return true; } else { return false; } } } } logWarning( 'Bad value specifier : ' + valueSpecifier ); return false; } // ~~ export function matchesConditionSpecifier( specifier, valueByNameMap ) { for ( let valueSpecifier of specifier.split( ',' ) ) { if ( matchesValueSpecifier( valueSpecifier, valueByNameMap ) ) { return true; } } return false; } // ~~ export function matchesTranslationSpecifier( translationSpecifier, valueByNameMap, languageTag ) { let conditionSpecifierArray = translationSpecifier.split( '?' ); if ( matchesLanguageSpecifier( conditionSpecifierArray[ 0 ], languageTag ) ) { for ( let conditionSpecifierIndex = 1; conditionSpecifierIndex < conditionSpecifierArray.length; ++conditionSpecifierIndex ) { if ( !matchesConditionSpecifier( conditionSpecifierArray[ conditionSpecifierIndex ], valueByNameMap ) ) { return false; } } return true; } return false; } // ~~ export function getSubstitutedText( text, valueByNameMap ) { if ( valueByNameMap !== undefined ) { for ( let [ name, value ] of Object.entries( valueByNameMap ) ) { text = text.replaceAll( substitutionPrefix + name + substitutionSuffix, value ); } } return text; } // ~~ export function getTranslatedText( multilingualText, valueByNameMap, languageTag_, defaultLanguageTag ) { if ( languageTag_ !== undefined && isString( valueByNameMap ) ) { languageTag_ = valueByNameMap; valueByNameMap = undefined; } let translatedTextArray = multilingualText.split( languageSeparator ); if ( languageTag_ === undefined ) { languageTag_ = languageTag; } if ( languageTag_ !== defaultLanguageTag ) { for ( let translatedTextIndex = translatedTextArray.length - 1; translatedTextIndex >= 1; --translatedTextIndex ) { let translatedText = translatedTextArray[ translatedTextIndex ]; let colonCharacterIndex = translatedText.indexOf( ':' ); if ( colonCharacterIndex >= 0 ) { if ( matchesTranslationSpecifier( translatedText.slice( 0, colonCharacterIndex ), valueByNameMap, languageTag_ ) ) { return getSubstitutedText( translatedText.slice( colonCharacterIndex + 1 ), valueByNameMap ); } } } } return getSubstitutedText( translatedTextArray[ 0 ], valueByNameMap ); } // ~~ export function getTranslatedNumber( number, decimalSeparator ) { if ( decimalSeparator === ',' ) { return number.toString().replace( '.', ',' ); } else { return number.toString(); } } // ~~ export function getLanguageDecimalSeparator( languageCode ) { if ( languageCode === 'en' || languageCode === 'ja' || languageCode === 'ko' || languageCode === 'zh' ) { return '.'; } else { return ','; } } // ~~ export function isMultilingualText( multilingualText ) { return multilingualText.indexOf( languageSeparator ) >= 0; } // ~~ export function getTranslationArray( multilingualText ) { let translatedTextArray = multilingualText.split( languageSeparator ); let translationArray = []; translationArray.push( { specifier : '', data : translatedTextArray[ 0 ] } ); for ( let translatedTextIndex = 1; translatedTextIndex < translatedTextArray.length; ++translatedTextIndex ) { let translatedText = translatedTextArray[ translatedTextIndex ]; let colonCharacterIndex = translatedText.indexOf( ':' ); if ( colonCharacterIndex >= 0 ) { translationArray.push( { specifier : translatedText.slice( 0, colonCharacterIndex ), data : translatedText.slice( colonCharacterIndex + 1 ) } ); } } return translationArray; } // ~~ export function getNextLanguageTag( languageTagArray, translationArray ) { for ( let languageTagIndex = 1; languageTagIndex < languageTagArray.length; ++languageTagIndex ) { let languageTag = languageTagArray[ languageTagIndex ]; for ( let translationIndex = 0; translationIndex < translationArray.length; ++translationIndex ) { let translation = translationArray[ translationIndex ]; if ( translation.specifier.indexOf( languageTag ) >= 0 ) { languageTag = ''; break; } } if ( languageTag !== '' ) { return languageTag; } } return ''; } // ~~ export function getMultilingualText( translationArray ) { let multilingualText = ''; if ( translationArray.length > 0 ) { multilingualText = translationArray[ 0 ].data; for ( let translationIndex = 1; translationIndex < translationArray.length; ++translationIndex ) { let translation = translationArray[ translationIndex ]; multilingualText += languageSeparator + translation.specifier + ':' + translation.data; } } return multilingualText; } // ~~ export function getLocalizedText( text, valueByNameMap, languageTag, defaultLanguageTag ) { if ( isMultilingualText( text ) ) { return getTranslatedText( text, valueByNameMap, languageTag, defaultLanguageTag ); } else { return text; } } // ~~ export function getLocalizedTextBySlug( textSlug, valueByNameMap, languageTag, defaultLanguageTag ) { if ( textBySlugMap.has( textSlug ) ) { return getLocalizedText( textBySlugMap.get( textSlug ), valueByNameMap, languageTag, defaultLanguageTag ); } else { logWarning( 'Missing text slug : ' + textSlug ); return textSlug; } }