summaryrefslogtreecommitdiff
path: root/src/jet/dependencies/locale.ts
blob: e48e935b125b7365378f558deb2f4338ad14d1c8 (plain)
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import type { Locale as JetLocaleDependency } from '@jet-app/app-store/foundation/dependencies/locale/locale';
import type {
    NormalizedLanguage,
    NormalizedStorefront,
    NormalizedLocale,
    UnnormalizedLocale,
} from '@jet-app/app-store/api/locale';
import type I18N from '@amp/web-apps-localization';
import type { Logger, LoggerFactory } from '@amp/web-apps-logger';

import type { Jet } from '~/jet/jet';
import {
    DEFAULT_STOREFRONT_CODE,
    DEFAULT_LANGUAGE_BCP47,
} from '~/constants/storefront';
import {
    type NormalizedLocaleWithDefault,
    normalizeStorefront,
    normalizeLanguage,
} from '~/utils/locale';
import type { Optional } from '@jet/environment';

/**
 * Contains information related to the locale of the request currently being
 * made to the application.
 *
 * Typically, localization information is expected to be known when the Jet
 * instance is initialized. The Web, however, will not know the current
 * locale and langauge until after routing has already taken place.
 *
 * This object exists to contain that lazily-determined locale information,
 * so that other dependencies can retreive it from here. It is to be created
 * with the rest of the dependencies and passed to them when they are created.
 *
 * Localization information is set in the {@linkcode Jet#setLocale} method
 */
export class Locale implements JetLocaleDependency {
    private readonly logger: Logger;

    private _storefront: NormalizedStorefront | undefined;
    private _language: NormalizedLanguage | undefined;

    i18n: I18N | undefined;

    constructor(loggerFactory: LoggerFactory) {
        this.logger = loggerFactory.loggerFor('locale');
    }

    get activeStorefront(): NormalizedStorefront {
        if (!this._storefront) {
            this.logger.warn('`storefront` was accessed before being set');
            return DEFAULT_STOREFRONT_CODE;
        }

        return this._storefront;
    }

    get activeLanguage(): NormalizedLanguage {
        if (!this._language) {
            this.logger.warn('`language` was accessed before being set');
            return DEFAULT_LANGUAGE_BCP47;
        }

        return this._language;
    }

    setActiveLocale(locale: NormalizedLocale): void {
        this._storefront = locale.storefront;
        this._language = locale.language;
    }

    normalize({
        storefront,
        language,
    }: UnnormalizedLocale): NormalizedLocaleWithDefault {
        const {
            storefront: normalizedStorefront,
            languages,
            defaultLanguage,
        } = normalizeStorefront(storefront);

        return {
            storefront: normalizedStorefront,
            ...normalizeLanguage(language || '', languages, defaultLanguage),
        };
    }

    deriveLocaleForUrl(locale: NormalizedLocale): {
        storefront: string;
        language: Optional<string>;
    } {
        const { isDefaultLanguage } = this.normalize(locale);

        return {
            storefront: locale.storefront,
            language: isDefaultLanguage ? undefined : locale.language,
        };
    }
}