locale.ts
1 import type { Locale as JetLocaleDependency } from '@jet-app/app-store/foundation/dependencies/locale/locale'; 2 import type { 3 NormalizedLanguage, 4 NormalizedStorefront, 5 NormalizedLocale, 6 UnnormalizedLocale, 7 } from '@jet-app/app-store/api/locale'; 8 import type I18N from '@amp/web-apps-localization'; 9 import type { Logger, LoggerFactory } from '@amp/web-apps-logger'; 10 11 import type { Jet } from '~/jet/jet'; 12 import { 13 DEFAULT_STOREFRONT_CODE, 14 DEFAULT_LANGUAGE_BCP47, 15 } from '~/constants/storefront'; 16 import { 17 type NormalizedLocaleWithDefault, 18 normalizeStorefront, 19 normalizeLanguage, 20 } from '~/utils/locale'; 21 import type { Optional } from '@jet/environment'; 22 23 /** 24 * Contains information related to the locale of the request currently being 25 * made to the application. 26 * 27 * Typically, localization information is expected to be known when the Jet 28 * instance is initialized. The Web, however, will not know the current 29 * locale and langauge until after routing has already taken place. 30 * 31 * This object exists to contain that lazily-determined locale information, 32 * so that other dependencies can retreive it from here. It is to be created 33 * with the rest of the dependencies and passed to them when they are created. 34 * 35 * Localization information is set in the {@linkcode Jet#setLocale} method 36 */ 37 export class Locale implements JetLocaleDependency { 38 private readonly logger: Logger; 39 40 private _storefront: NormalizedStorefront | undefined; 41 private _language: NormalizedLanguage | undefined; 42 43 i18n: I18N | undefined; 44 45 constructor(loggerFactory: LoggerFactory) { 46 this.logger = loggerFactory.loggerFor('locale'); 47 } 48 49 get activeStorefront(): NormalizedStorefront { 50 if (!this._storefront) { 51 this.logger.warn('`storefront` was accessed before being set'); 52 return DEFAULT_STOREFRONT_CODE; 53 } 54 55 return this._storefront; 56 } 57 58 get activeLanguage(): NormalizedLanguage { 59 if (!this._language) { 60 this.logger.warn('`language` was accessed before being set'); 61 return DEFAULT_LANGUAGE_BCP47; 62 } 63 64 return this._language; 65 } 66 67 setActiveLocale(locale: NormalizedLocale): void { 68 this._storefront = locale.storefront; 69 this._language = locale.language; 70 } 71 72 normalize({ 73 storefront, 74 language, 75 }: UnnormalizedLocale): NormalizedLocaleWithDefault { 76 const { 77 storefront: normalizedStorefront, 78 languages, 79 defaultLanguage, 80 } = normalizeStorefront(storefront); 81 82 return { 83 storefront: normalizedStorefront, 84 ...normalizeLanguage(language || '', languages, defaultLanguage), 85 }; 86 } 87 88 deriveLocaleForUrl(locale: NormalizedLocale): { 89 storefront: string; 90 language: Optional<string>; 91 } { 92 const { isDefaultLanguage } = this.normalize(locale); 93 94 return { 95 storefront: locale.storefront, 96 language: isDefaultLanguage ? undefined : locale.language, 97 }; 98 } 99 }