import { Injectable } from '@angular/core' ; import { BehaviorSubject , combineLatest , Observable , of } from 'rxjs' ; import { catchError , map } from 'rxjs/operators' ; import { CookieService } from '../../common/services/cookie.service' ; import { ApiService } from '../../common/api/api.service' ; import { Session } from '../../services/session' ; import { ConfigsService } from '../../common/services/configs.service' ; import * as moment from 'moment' ; /**
 * Language list entry structure
 */ export interface LanguageListEntry { code : string ; name : string ; } const isoCodeToLanguageName = ( [ languages , currentLanguage ] ) => languages . find ( language => language . code === currentLanguage ) . name ; const POPULAR_LANGUAGE_CODES = [ 'en' , 'es' , 'de' , 'fr' , 'th' , 'it' ] ; /**
 * Language service
 */ @ Injectable ( ) export class LanguageService { /**
     * Current language selected by user
     */ readonly currentLanguage$ : BehaviorSubject < string > = new BehaviorSubject < string > ( 'en' ) ; /**
     * Browser's language
     */ readonly browserLanguage$ : Observable < string > = of ( ( navigator as any ) . language || ( navigator as any ) . userLanguage ) . pipe ( map < string , string > ( language => ( language || 'en' ) . slice ( 0 , 2 ) . toLowerCase ( ) ) ) ; /**
     * List of all languages, weighted by current, browser and site default (English)
     */ readonly languages$ : Observable < Array < LanguageListEntry > > = combineLatest ( [ of ( this . configs . get ( 'languages' ) ) . pipe ( map ( languages => { const arr = [ ] ; for ( const code in languages ) { if ( languages . hasOwnProperty ( code ) ) { arr . push ( { code , name : languages [ code ] , } ) ; } } return arr ; } ) ) , this . currentLanguage$ , this . browserLanguage$ , ] ) . pipe ( map ( ( [ languages , current , browser ] ) => this . sortLanguageList ( languages , current , browser ) ) ) ; /**
     * Current's language native name
     */ readonly currentLanguageName$ : Observable < string > = combineLatest ( [ this . languages$ , this . currentLanguage$ , ] ) . pipe ( map ( isoCodeToLanguageName ) , catchError ( ( ) => 'Unknown' ) ) ; /**
     * Browser's language native name
     */ readonly browserLanguageName$ : Observable < string > = combineLatest ( [ this . languages$ , this . browserLanguage$ , ] ) . pipe ( map ( isoCodeToLanguageName ) , catchError ( ( ) => 'Unknown' ) ) ; param cookie param api param session param configs constructor ( protected cookie , protected api , protected session , protected configs ) { const currentLanguage = this . cookie . get ( 'hl' ) ; if ( currentLanguage ) { this . setCurrentLanguage ( currentLanguage , true ) ; } } param language param serviceOnly async setCurrentLanguage ( language , serviceOnly = false ) { this . currentLanguage$ . next ( language ) ; moment . locale ( language ) ; if ( ! serviceOnly ) { if ( this . session . isLoggedIn ( ) ) { await this . api . post ( 'api/v1/settings' , { language , } ) . toPromise ( ) ; } else { this . cookie . put ( 'hl' , language ) ; } return true ; } return false ; } param languages param current param browser protected sortLanguageList ( languages , current , browser ) { const defaultLanguageCode = 'en' ; const score = ( { code } ) : number => { let score = 0 ; if ( POPULAR_LANGUAGE_CODES . indexOf ( code ) > - 1 ) { score += 1 ; } if ( code === defaultLanguageCode ) { score += 1 ; } if ( code === browser ) { score += 2 ; } if ( code === current ) { score += 4 ; } return score ; } ; return languages . sort ( ( a , b ) => score ( b ) - score ( a ) ) ; } }