{"version":3,"file":"bespunky-angular-zen-language.mjs","sources":["../../../../libs/angular-zen/language/src/config/language-integration-config.ts","../../../../libs/angular-zen/language/src/services/language-integration.service.ts","../../../../libs/angular-zen/language/src/url-localization/localizers/url-localizer.ts","../../../../libs/angular-zen/language/src/url-localization/config/url-localization-config.ts","../../../../libs/angular-zen/language/src/url-localization/localizers/route-position-url-localizer.ts","../../../../libs/angular-zen/language/src/url-localization/localizers/query-params-url-localizer.ts","../../../../libs/angular-zen/language/src/url-localization/localizers/noop-url-localizer.ts","../../../../libs/angular-zen/language/src/url-localization/config/url-localization.provider.ts","../../../../libs/angular-zen/language/src/config/language-integration.provider.ts","../../../../libs/angular-zen/language/src/language-integration.module.ts","../../../../libs/angular-zen/language/src/services/localized-route-aware.service.ts","../../../../libs/angular-zen/language/src/url-localization/services/url-localization.service.ts","../../../../libs/angular-zen/language/src/bespunky-angular-zen-language.ts"],"sourcesContent":["import { Observable     } from 'rxjs';\nimport { InjectionToken } from '@angular/core';\n\nimport { SupportedLanguagesFactory, DefaultLanguageFactory, TranslationFn, ObservableLike } from './language-integration-types';\n\n/**\n * Configuration for integrating language services into a library.\n * Used in `LanguageIntegrationModule.forRoot()`.\n *\n * @export\n * @interface LanguageIntegrationConfig\n */\nexport interface LanguageIntegrationConfig\n{\n    /**\n     * The languages supported by the integrated app (e.g. 'en', 'fr', 'en-US', 'es-CL').\n     * This can be a local array or a resolvable async factory which returns the language names.\n     * \n     * When providing a factory returning an observable, it is the app's responsability to provide an auto completing observable.\n     * A common way would be to pipe `take(1)` to make the observable complete after one emission.\n     * \n     * Observables left open will cause memory leaks in the language integration service.\n     * \n     * @type {(string[] | SupportedLanguagesFactory)}\n     */\n    supported: string[] | SupportedLanguagesFactory;\n    /**\n     * The default language used by the integrated app (e.g. 'en', 'fr', 'en-US', 'es-CL').\n     * This can be a local array or a resolvable async factory which returns the language names.\n     *\n     * When providing a factory returning an observable, it is the app's responsability to provide an auto completing observable.\n     * A common way would be to pipe `take(1)` to make the observable complete after one emission.\n     * \n     * Observables left open will cause memory leaks in the language integration service.\n     *\n     * @type {(string | DefaultLanguageFactory)}\n     */\n    default: string | DefaultLanguageFactory;\n    /**\n     * (Optional) A resolvable async object which emits once, when the intgrated language services are ready for operation.\n     * \n     * Provide a value if you need to control and delay the execution of language related operations.\n     * \n     * @type {ObservableLike<any>}\n     */\n    ready?: ObservableLike<any>;\n    /**\n     * A subscribable object which emits every time the integrated app has changed the current language.\n     * The observable should emit the new language name  (e.g. 'en', 'fr', 'en-US', 'es-CL').\n     *\n     * @type {Observable<string>}\n     */\n    changed: Observable<string>;\n    /**\n     * The function used for live translation.\n     *\n     * @type {TranslationFn}\n     */\n    translate: TranslationFn;\n}\n\n/**\n * An injection token representing the the global language integration configuration provided by an app to its libraries.\n * Provided by `LanguageIntegrationModule.forRoot()`.\n */\nexport const LanguageIntegration = new InjectionToken<LanguageIntegrationConfig>('LanguageIntegration.Config');\n","/* eslint-disable @typescript-eslint/no-non-null-assertion */\nimport { from, of, Observable         } from 'rxjs';\nimport { Inject, Injectable, Optional } from '@angular/core';\n\nimport { Destroyable                                    } from '@bespunky/angular-zen/core';\nimport { access                                         } from '@bespunky/angular-zen/utils';\nimport { LanguageIntegrationConfig, LanguageIntegration } from '../config/language-integration-config';\n\n/**\n * Uses the language integration configuration provided by an app to provide language services for a library.\n * @see `LanguageIntegrationModule.forRoot()`.\n * \n * @export\n * @class LanguageIntegrationService\n * @extends {Destroyable}\n */\n@Injectable({ providedIn: 'root' })\nexport class LanguageIntegrationService extends Destroyable\n{\n    private $ready!        : Observable<void>;\n    private defaultLang?   : string;\n    private supportedLangs?: string[];\n    private currentLang?   : string;\n\n    /**\n     * Creates an instance of LanguageIntegrationService.\n     * \n     * @param {LanguageIntegrationConfig} [config] The language integration configuration provided using `LanguageIntegrationModule.forRoot()`.\n     */\n    constructor(@Optional() @Inject(LanguageIntegration) public readonly config?: LanguageIntegrationConfig)\n    {\n        super();\n\n        this.initReadyObservable();\n\n        if (config) this.initMultiLanguageSupport();\n    }\n    \n    private initReadyObservable(): void\n    {\n        const ready = this.config?.ready;\n\n        // Using of() instead of EMPTY as EMPTY only calls `complete` but not `next`.\n        // This allows users to subscribe more intuitively.\n        this.$ready = ready ? from(ready) : of();\n    }\n\n    private initMultiLanguageSupport(): void\n    {\n        this.subscribe(this.config!.changed, lang => this.currentLang = lang);\n\n        // User's responsability to provide a completing observables.\n        this.loadDefaultLanguage   ().subscribe(defaultLang => this.defaultLang    = defaultLang);\n        this.loadSupportedLanguages().subscribe(languages   => this.supportedLangs = languages);\n    }\n\n    private loadDefaultLanguage(): Observable<string>\n    {\n        const defaultLang = this.config!.default;\n    \n        return typeof defaultLang === 'string' ? of(defaultLang) : from(defaultLang());\n    }\n\n    private loadSupportedLanguages(): Observable<string[]>\n    {\n        const supported = this.config!.supported;\n        \n        return Array.isArray(supported) ? of(supported) : from(supported());\n    }\n\n    /**\n     * A subscribable event emitting every time the integrated app changes a language.\n     * The new language name is emitted with each change.\n     *\n     * This will be `undefined` if the language integration module hasn't been imported by the app.\n     * \n     * @readonly\n     * @type {Observable<string> | undefined}\n     */\n    public get changed(): Observable<string> | undefined\n    {\n        return this.config?.changed;\n    }\n\n    /**\n     * The default language used by the integrated app.\n     *\n     * This will be `undefined` in the following cases:\n     * 1. The language integration module hasn't been imported by the app.\n     * 2. The default language hasn't resolved yet.\n     * \n     * @readonly\n     * @type {string | undefined}\n     */\n    public get default(): string | undefined\n    {\n        return this.defaultLang;\n    }\n\n    /**\n     * The languages supported by the integrated app.\n     *\n     * This will be `undefined` in the following cases:\n     * 1. The language integration module hasn't been imported by the app.\n     * 2. Supported languages haven't resolved yet.\n     *\n     * @readonly\n     * @type {string[] | undefined}\n     */\n    public get supported(): string[] | undefined\n    {\n        return this.supportedLangs;\n    }\n\n    /**\n     * The current language used by the integrated app.\n     *\n     * This will be `undefined` in the following cases:\n     * 1. The language integration module hasn't been imported by the app.\n     * 2. The `changed` event hasn't emitted yet.\n     *\n     * @readonly\n     * @type {string | undefined}\n     */\n    public get current(): string | undefined\n    {\n        return this.currentLang;\n    }\n    \n    /**\n     * Indicated whether the language integration module has been imported into the app.\n     * If this is `false`, this service will serve no purpose.\n     *\n     * @readonly\n     * @type {boolean}\n     */\n    public get enabled()\n    {\n        return !!(this.config);\n    }\n\n    /**\n     * A resolvable async object which emits once when the intgrated language services are ready for operation.\n     * \n     * This will complete immediately if the the language integration module hasn't been imported, or a `ready` observable hasn't\n     * been provided when importing the module.\n     *\n     * @readonly\n     * @type {Observable<void>}\n     */\n    public get ready(): Observable<void>\n    {\n        return this.$ready;\n    }\n\n    /**\n     * Retrieves the list of alternative languages to the specified language supported by the integrated app.\n     *\n     * @param {string} lang The language for which to get the alternative languages.\n     * @returns {string[]} An array of alternative languages supported by the integrated app.\n     * @throws If the language integration module hasn't been imported into the app.\n     */\n    public alternateLanguagesFor(lang: string): string[]\n    {\n        this.ensureEnabled();\n        \n        return this.supported!.filter(supportedLocale => supportedLocale !== lang);\n    }\n    \n    /**\n     * Translates a value (typically a translation id) into the current language used by the integrated app.\n     *\n     * @param {string} value The value to translate (typically a translation id).\n     * @param {Record<string, unknown>} [params] (Optional) Any params needed for translating the value.\n     * @returns {string} The translation of the specified value and params in the current language used by the integrated app.\n     * @throws If the language integration module hasn't been imported into the app.\n     */\n    public translate(value: string, params?: Record<string, unknown>): string\n    {\n        this.ensureEnabled();\n\n        return this.config!.translate(value, params);\n    }\n\n    /**\n     * Dives deep into an object or an array and replaces the indicated properties in-place with their translation. \n     *\n     * The `paths` argument is an array of paths representing deep properties which should be translated.\n     * For example:\n     * \n     * ```typescript\n     * // If we have a user object, we can translate its city and role properties\n     * {\n     *     id: 15,\n     *     addresses: [\n     *         { city: 'Tel Aviv', ... },\n     *         { city: 'Rishon LeTzion' }\n     *     ],\n     *     system: {\n     *         role: 'Admin'\n     *     }\n     * }\n     * \n     * // Our paths would be:\n     * `addresses[0].city`\n     * `addresses[1].city`\n     * `system.role`\n     * ```\n     * \n     * @param {Record<string, unknown>} data The object which holds the translatable properties. Can be a deeply nested object.\n     * @param {string[]} paths The paths of the translatable properties to translate and replace.\n     * @throws If the language integration module hasn't been imported into the app.\n     */\n    public translateProperties(data: Record<string, unknown>, paths: string[]): void\n    {\n        this.ensureEnabled();\n        \n        paths.forEach(path =>\n        {\n            const valueAccessor = access<string>(data, path);\n            const value = valueAccessor.get();\n\n            if (typeof value !== 'string') return;\n\n            valueAccessor.set(this.translate(value));\n        });\n    }\n    \n    /**\n     * Ensures that the language integration module has been imported and a configuration object has been provided.\n     * \n     * @throws {Error} The language integration module hasn't been imported by the app.\n     */\n    public ensureEnabled(): this is { config: LanguageIntegrationConfig }\n    {\n        if (this.enabled) return true;\n\n        throw new Error(`\n            Language integration hasn't been enabled.\n            Did you import the language integration module in your app module using 'LanguageIntegrationModule.forRoot()'?\n        `);\n    }\n}","import { Injectable } from '@angular/core';\n\nimport { UrlReflectionService } from '@bespunky/angular-zen/router-x';\n\n/**\n * The base class for url localization implementors. This can be used as an injectable token to get a hold of the currently\n * configured url localizer class.\n *\n * @export\n * @abstract\n * @class UrlLocalizer\n */\n@Injectable()\nexport abstract class UrlLocalizer\n{\n    /**\n     * Creates an instance of UrlLocalizer.\n     * \n     * @param {UrlReflectionService} urlReflection The url reflection service.\n     */\n    constructor(protected urlReflection: UrlReflectionService) { }\n\n    /**\n     * Reads the currently navigated url and localizes it to the specified language.\n     * If the url is already localized with a different language, updates the language.\n     * If the url is already localized with the specified language, returns the url unchanged.\n     * \n     * @abstract\n     * @param {string} lang The language code to use for localization (e.g. 'en', 'fr', 'en-US', 'es-CL').\n     * @returns {string} The localized url.\n     */\n    public abstract localize(lang: string): string;\n\n    /**\n     * Reads the Currently navigated url and delocalizes it.\n     * If the url is already delocalized, return the url unchanged.\n     *\n     * @abstract\n     * @returns {string} The delocalized url.\n     */\n    public abstract delocalize(): string;\n}\n","import { ClassProvider, FactoryProvider, InjectionToken, Type } from '@angular/core';\n\nimport { UrlLocalizer } from '../localizers/url-localizer';\n\n/** Represents a factory function for building a `UrlLocalizer` using dependency injection. */\nexport type UrlLocalizerFactory = (...deps: any[]) => UrlLocalizer;\n\n/**\n * A strongly-typed factory provider for creating a `UrlLocalizer` using dependency injection.\n *\n * @export\n * @interface UrlLocalizerFactoryProvider\n * @extends {(Omit<FactoryProvider, 'provide' | 'multi'>)}\n */\nexport interface UrlLocalizerFactoryProvider extends Omit<FactoryProvider, 'provide' | 'multi'>\n{\n    /**\n     * The factory to use for instantiating a `UrlLocalizer` object.\n     *\n     * @type {UrlLocalizerFactory}\n     */\n    useFactory: UrlLocalizerFactory;\n}\n\n/**\n * A strongly-typed class provider for instantiating a `UrlLocalizer`.\n *\n * @export\n * @interface UrlLocalizerClassProvider\n * @extends {(Omit<ClassProvider, 'provide' | 'multi'>)}\n */\nexport interface UrlLocalizerClassProvider extends Omit<ClassProvider, 'provide' | 'multi'>\n{\n    /**\n     * The class to use as a url localizer.\n     *\n     * @type {Type<UrlLocalizer>}\n     */\n    useClass: Type<UrlLocalizer>;\n}\n\n/** Represents the supported types of strategies for url localization. */\nexport type UrlLocalizationStrategy = number | string | UrlLocalizerFactoryProvider | UrlLocalizerClassProvider;\n\n/** Represents the configutaration for url localization tools. */\nexport interface UrlLocalizationConfig\n{\n    /**\n     * The strategy to use for url localization. Can be a:  \n     * `Number`\n     * - Positive numbers express the position of the language param from the start of the route.\n     * - Negative numbers express the position of the language param from the end of the route.\n     * - Zero is ignored and will cause no change to the url.\n     * \n     * `String`\n     * - The name of the query param specifying the current language.\n     * \n     * `UrlLocalizerFactoryProvider`\n     * - A provider for a factory for instantiating a `UrlLocalizer` object using dependency injection.\n     * \n     * `UrlLocalizerClassProvider`\n     * - A provider for an extending `UrlLocalizer` class.\n     * @type {UrlLocalizationStrategy}\n     */\n    strategy   : UrlLocalizationStrategy;\n    /**\n     * (Optional) Indicates whether localization and delocalization of a url should always return an https prefix.\n     * Default is `false`.\n     * @type {boolean}\n     */\n    forceHttps?: boolean;\n}\n\n/**\n * An injection token for the provided url localization configuration.\n * `LanguageIntegrationModule.forRoot()` facilitates the injection of this token. No need to inject directly.\n */\nexport const UrlLocalization = new InjectionToken<UrlLocalizationConfig>('LanguageIntegration.UrlLocalizationConfig');","import { Inject, Injectable } from '@angular/core';\n\nimport { UrlReflectionService                   } from '@bespunky/angular-zen/router-x';\nimport { LanguageIntegrationService             } from '../../services/language-integration.service';\nimport { UrlLocalization, UrlLocalizationConfig } from '../config/url-localization-config';\nimport { UrlLocalizer                           } from './url-localizer';\n\n/**\n * Provides tools for localization and delocalization of the currently navigated url by adding or removing\n * a route segment dedicated for language.\n *\n * @export\n * @class RoutePositionUrlLocalizer\n * @extends {UrlLocalizer}\n */\n@Injectable({ providedIn: 'root'})\nexport class RoutePositionUrlLocalizer extends UrlLocalizer\n{\n    /**\n     * The position of the language segment in the route of the currently navigated url.\n     * Positive numbers indicate position from the beginning of the route.\n     * Negative numbers indicate position from the end of the route.\n     * Zero is ignored and will cause methods to return an unchanged url.\n     * \n     * @type {number}\n     */\n    public readonly position: number;\n\n    constructor(\n        @Inject(UrlLocalization) { strategy }   : UrlLocalizationConfig,\n                                   urlReflection: UrlReflectionService,\n                           private language     : LanguageIntegrationService\n    )\n    {\n        super(urlReflection);\n\n        this.position = strategy as number;\n    }\n\n    /**\n     * Localizes the currently navigated url by adding or updating the language segment of the route.\n     * If `position` is positive, language lookup will be performed from the beginning of route.\n     * If `position` is negative, language lookup will be performed from the end of route.\n     * If `position` points to an index out of bounds, the last/first element will be treated as the language.\n     *\n     * #### Example\n     * Position  1 - /en/some/route - first segment from the left.  \n     * Position  2 - /some/en/route - second segment from the left.  \n     * Position  5 - /some/route/en - out of bounds. last segment from the left.  \n     *   \n     * Position -1 - /some/route/en - first segment from the right.  \n     * Position -2 - /some/en/route - second segment from the right.  \n     * Position -5 - /en/some/route - out of bounds. last segment from the right.  \n     * \n     * @param {string} lang\n     * @returns {string} The currently navigated url localized to the specified language.\n     */\n    localize(lang: string): string\n    {\n        return this.transformUrl(\n            (segments, langIndex, isLanguage) => this.insertOrReplaceLanguage(lang, segments, langIndex, isLanguage)\n        );\n    }\n\n    /**\n     * Delocalizes the currently navigated url by removing the language segment from the route.\n     * If `position` is positive, language lookup will be performed from the beginning of route.\n     * If `position` is negative, language lookup will be performed from the end of route.\n     * If `position` points to an index out of bounds, the last/first element will be treated as the language.\n     * If no language exists at the language position, returns the url unchanged.\n     *\n     * #### Example\n     * Position  1 - /en/some/route - first segment from the left.  \n     * Position  2 - /some/en/route - second segment from the left.  \n     * Position  5 - /some/route/en - out of bounds. last segment from the left.  \n     *   \n     * Position -1 - /some/route/en - first segment from the right.  \n     * Position -2 - /some/en/route - second segment from the right.  \n     * Position -5 - /en/some/route - out of bounds. last segment from the right.  \n     * \n     * @returns {string} The delocalized currently navigated url.\n     */\n    delocalize(): string\n    {\n        return this.transformUrl(\n            (segments, langIndex, isLanguage) => this.removeLanguage(segments, langIndex, isLanguage),\n            // When removing the language segment, the index should always be in range. Unlike when inserting, an overflowing index\n            // will not be converted to the last index automatically by `.splice()`.\n            (segments, langIndex            ) => langIndex >= segments.length ? segments.length - 1: langIndex\n        );\n    }\n    \n    private transformUrl(transform: (segments: string[], langIndex: number, isLanguage: boolean) => void, sanitizeIndex?: (segments: string[], langIndex: number) => number): string\n    {\n        // Position of zero will not touch the url as zero's functionality is not defined\n        if (this.position === 0) return this.urlReflection.fullUrl;\n\n        const segments = this.urlReflection.routeSegments;\n        // Convert the position to replace/add to an index (might result in large negatives or positives, exceeding array bounds)\n        let langIndex  = this.indexOfPosition();\n        \n        this.accessSegmentsSafely(segments, () =>\n        {\n            if (sanitizeIndex) langIndex = sanitizeIndex(segments, langIndex);\n            // Determine if a language segment exists at the specified index\n            const isLanguage = this.isLanguage(segments[langIndex]);\n\n            return transform(segments, langIndex, isLanguage);\n        });\n\n        return this.composeUrl(segments);\n    }\n\n    /**\n     * Updates the specified route segments array with the specified language.\n     *\n     * @protected\n     * @param {string} lang The new language to set to the route.\n     * @param {string[]} segments The current route segments.\n     * @param {number} langIndex The index of the expected language segment.\n     * @param {boolean} isLanguage `true` if the current value at `langIndex` is a supported language; otherwise `false`.\n     */\n    protected insertOrReplaceLanguage(lang: string, segments: string[], langIndex: number, isLanguage: boolean): void\n    {\n        // Define how many items to remove. If the segment is already a language and should be replaced, zero items should be removed.\n        const deleteCount = isLanguage ? 1 : 0;\n\n        // Replace existing language segment or add a new one. If the specified index exceeds the length of the array, splice will add a new item at the end/beginning of the array.\n        segments.splice(langIndex, deleteCount, lang);\n    }\n\n    /**\n     * Removes the language segment from a route segments array.\n     * If the language index points to a non-language segment, returns without changing the segments.\n     *\n     * @protected\n     * @param {string[]} segments The current route segments.\n     * @param {number} langIndex The index of the expected langauge segment.\n     * @param {boolean} isLanguage `true` if the current value at `langIndex` is a supported language; otherwise `false`.\n     */\n    protected removeLanguage(segments: string[], langIndex: number, isLanguage: boolean): void\n    {\n        if (!isLanguage) return;\n\n        segments.splice(langIndex, 1);\n    }\n\n    /**\n     * Accessing segments by index requires the `this.position` to be translated into an index.\n     * As the position can either be positive or negative, there are two different formulas for index calculation.\n     * In turn, this means two different scenarios with different edge cases.\n     * \n     * To unify the cases and reduce complexity, when position is negative, this method reverses the segments array, runs the segments manipulation, then reverses it again to restore the original order.\n     * This way the indexing is always done from one side of the array.\n     * \n     * @protected\n     * @param {string[]} segments The segments about to be manipulated.\n     * @param {() => void} accessSegments The function that needs safe access by index to the \n     */\n    protected accessSegmentsSafely(segments: string[], accessSegments: () => void): void\n    {\n        if (this.isNegativeLookup) segments.reverse();\n        \n        accessSegments();\n        \n        if (this.isNegativeLookup) segments.reverse();\n    }\n\n    /**\n     * Indicates whether the configured language position is positive, resulting in a lookup from the left (positive lookup).\n     * `true` if positive lookup should be performed; otherwise `false`.\n     * \n     * @readonly\n     * @protected\n     * @type {boolean}\n     */\n    protected get isPositiveLookup(): boolean\n    {\n        return this.position > 0;\n    }\n\n    /**\n     * Indicates whether the configured language position is negative, resulting in a lookup from the right (negative lookup).\n     * `true` if negative lookup should be performed; otherwise `false`.\n     *\n     * @readonly\n     * @protected\n     * @type {boolean}\n     */\n    protected get isNegativeLookup(): boolean\n    {\n        return this.position < 0;\n    }\n\n    /**\n     * Calculates the absolute index for the configured language position.\n     *\n     * @protected\n     * @returns {number}\n     */\n    protected indexOfPosition(): number\n    {\n        return Math.abs(this.position) - 1;\n    }\n\n    /**\n     * Checks whether the specified value is a language supported by the language integration services.\n     *\n     * @protected\n     * @param {string} value The value to check.\n     * @returns {boolean} `true` if the value is a supported language; otherwise `false`.\n     */\n    protected isLanguage(value: string): boolean\n    {\n        return this.language.supported?.includes(value) || false;\n    }\n\n    /**\n     * Concats the host url as given by the url reflection service with the segments and the current query string to create\n     * a fully qualified url.\n     *\n     * @protected\n     * @param {string[]} segments The route segments to place in the url.\n     * @returns {string} The fully qualified url composed of the host url as given by the url reflection service, the specified route segments, and the current query params.\n     */\n    protected composeUrl(segments: string[]): string\n    {\n        const { hostUrl, queryString } = this.urlReflection;\n\n        return `${hostUrl}/${segments.join('/')}${queryString}`\n    }\n}","import { Inject, Injectable } from '@angular/core';\nimport { UrlTree            } from '@angular/router';\n\nimport { UrlReflectionService                   } from '@bespunky/angular-zen/router-x';\nimport { UrlLocalization, UrlLocalizationConfig } from '../config/url-localization-config';\nimport { UrlLocalizer                           } from './url-localizer';\n\n/**\n * Provides tools for localization and delocalization of the currently navigated url by adding or removing\n * a named query param dedicated for language.\n *\n * @export\n * @class QueryParamsUrlLocalizer\n * @extends {UrlLocalizer}\n */\n@Injectable({ providedIn: 'root'})\nexport class QueryParamsUrlLocalizer extends UrlLocalizer\n{\n    /**\n     * The name of the query parameter specifying the language.\n     *\n     * @type {string}\n     */\n    public readonly paramName: string;\n\n    constructor(@Inject(UrlLocalization) { strategy }: UrlLocalizationConfig, urlReflection: UrlReflectionService)\n    {\n        super(urlReflection);\n\n        this.paramName = strategy as string;\n    }\n\n    /**\n     * Localizes the currently navigated url by adding or updating the query param specifying the language.\n     *\n     * @param {string} lang The new language of the url.\n     * @returns {string} The currently navigated url localized into the specified language.\n     */\n    localize(lang: string): string\n    {\n        const currentUrlTree    = this.parseUrlTree();\n        const localizedParams   = this.replaceLanguageParam(this.urlReflection.queryParams, lang);\n        const localizedRoute    = this.replaceQueryParamsInUrlTree(currentUrlTree, localizedParams);\n        const localizedRouteUrl = this.urlReflection.router.serializeUrl(localizedRoute);\n\n        return this.composeUrl(localizedRouteUrl);\n    }\n    \n    /**\n     * Delocalizes the currently navigated url by removing the query param specifying the language.\n     *\n     * @returns {string} The currently navigated url without the query param for language.\n     */\n    delocalize(): string\n    {\n        return this.localize('');\n    }\n\n    /**\n     * Returns the `UrlTree` representing the currently navigated url.\n     *\n     * @protected\n     * @returns {UrlTree} The `UrlTree` representing the currently navigated url.\n     */\n    protected parseUrlTree(): UrlTree\n    {\n        const { router } = this.urlReflection;\n\n        // Parsing the url seems dumb as the router should have it parsed already, but the route object doesn't hold\n        // the tree and the router SOMETIMES holds it in getCurrentNavigation().\n        return router.parseUrl(router.url);\n    }\n\n    /**\n     * Updates the language param in a query params object.\n     *\n     * @protected\n     * @param {*} params The object representing the query params.\n     * @param {string} lang The new language to set to the language query param. If `null` or `undefined`, the language query param will be deleted from the object.\n     * @returns {*} The updated query params object.\n     */\n    protected replaceLanguageParam(params: any, lang: string): any\n    {\n        if (lang)\n            params[this.paramName] = lang;\n        else\n            delete params[this.paramName];\n\n        return params;\n    }\n\n    /**\n     * Replaces the query params in a url tree object.\n     *\n     * @protected\n     * @param {UrlTree} url The url tree in which query params should be replaced.\n     * @param {Object} newParams The new query params object to set to the url tree.\n     * @returns {UrlTree} The updated url tree object.\n     */\n    protected replaceQueryParamsInUrlTree(url: UrlTree, newParams: { [k: string]: any }): UrlTree\n    {\n        return Object.assign(url, { queryParams: newParams });\n    }\n\n    /**\n     * Concats the host url and the specified route url to compose a fully qualified url.\n     * Uses the host url provided by the url reflection service.\n     * \n     * @protected\n     * @param {string} routeUrl The route url to concat to the host url. Should be prefixed with '/'.\n     * @returns {string} The fully qualified url composed of the host url defined by the url reflection service and the specified route url.\n     */\n    protected composeUrl(routeUrl: string): string\n    {      \n        const { hostUrl } = this.urlReflection;\n\n        return `${hostUrl}${routeUrl}`;\n    }\n}","import { Injectable } from '@angular/core';\n\nimport { UrlLocalizer } from './url-localizer';\n\n/**\n * A noop implemetation for the `UrlLocalizer` class.\n * Always returns unchanged urls.\n *\n * @export\n * @class NoopUrlLocalizer\n * @extends {UrlLocalizer}\n */\n@Injectable({ providedIn: 'root'})\nexport class NoopUrlLocalizer extends UrlLocalizer\n{\n    /**\n     * Returns the currently navigated url as is.\n     *\n     * @param {string} lang Ignore.\n     * @returns {string} The currently navigated url as is.\n     */\n    localize(lang: string): string\n    {\n        return this.urlReflection.fullUrl;\n    }\n    \n    /**\n     * Returns the currently navigated url as is.\n     *\n     * @returns {string} The currently navigated url as is.\n     */\n    delocalize(): string\n    {\n        return this.urlReflection.fullUrl;\n    }\n}","import { ClassProvider, FactoryProvider, Provider } from '@angular/core';\n\nimport { UrlReflectionService                   } from '@bespunky/angular-zen/router-x';\nimport { LanguageIntegrationService             } from '../../services/language-integration.service';\nimport { UrlLocalizer                           } from '../localizers/url-localizer';\nimport { RoutePositionUrlLocalizer              } from '../localizers/route-position-url-localizer';\nimport { QueryParamsUrlLocalizer                } from '../localizers/query-params-url-localizer';\nimport { NoopUrlLocalizer                       } from '../localizers/noop-url-localizer';\nimport { UrlLocalizationConfig, UrlLocalization } from './url-localization-config';\n\n/**\n * The default configuration for url localization when loading the language integration module.\n * Uses the `NoopUrlLocalizer` as strategy and does not force https. Localization and delocalization will always return an unchanged url url.\n */\nexport const DefaultUrlLocalizationConfig: UrlLocalizationConfig = {\n    strategy  : { useClass: NoopUrlLocalizer },\n    forceHttps: false\n};\n\n/**\n * Creates the appropriate DI compatible provider for the `UrlLocalizer` class, depending on the strategy specified in the url localization configuration.  \n * If the configured strategy is a number, `RoutePositionUrlLocalizer` will be used.  \n * If the configured strategy is a string, `QueryParamsUrlLocalizer` will be used.  \n * If the configured strategy is a valid `UrlLocalizer` provider, the provider will be used as is.  \n * Otherwise, `NoopUrlLocalizer` will be used.\n * \n * @export\n * @param {UrlLocalizationConfig} config The url localization configuration holding the strategy.\n * @returns {(ClassProvider | FactoryProvider)} A DI compatible provider for the `UrlLocalizer` class with the implementation appropriate for the specified strategy.\n */\nexport function provideUrlLocalizer(config: UrlLocalizationConfig): ClassProvider | FactoryProvider\n{\n    const strategy = config?.strategy;\n\n    const strategies: { [type: string]: () => Partial<Provider>; } = {\n        // Use route position strategy for numbers\n        number   : () => ({ useFactory: (urlReflect: UrlReflectionService, language: LanguageIntegrationService) => new RoutePositionUrlLocalizer(config, urlReflect, language), deps: [UrlReflectionService, LanguageIntegrationService] }),\n        // Use query params strategy for strings\n        string   : () => ({ useFactory: (urlReflect: UrlReflectionService) => new QueryParamsUrlLocalizer(config, urlReflect), deps: [UrlReflectionService] }),\n        // Use the user's factory or class provider\n        object   : () => strategy,\n        // Use the noop localizer when nothing provided (in case url localization config is not present)\n        undefined: () => ({ useClass: NoopUrlLocalizer })\n    };\n\n    // Create a basic provider to which the strategy will be assigned\n    const provider: Partial<Provider> = { provide: UrlLocalizer };\n\n    // Override the useClass or useFactory with the detected strategy\n    return Object.assign(provider, strategies[typeof strategy]()) as (ClassProvider | FactoryProvider);\n}\n\n/**\n * Creates the providers for the `UrlLocalization` token and the `UrlLocalizer` class.\n *\n * @export\n * @param {UrlLocalizationConfig} [config] (Optional) The configuration for url localization tools. Default is `DefaultUrlLocalizationConfig`.\n * @returns {Provider[]} The providers for the `UrlLocalization` token and the `UrlLocalizer` class.\n */\nexport function provideUrlLocalization(config?: UrlLocalizationConfig): Provider[]\n{\n    config = Object.assign({}, DefaultUrlLocalizationConfig, config);\n\n    return [\n        { provide: UrlLocalization, useValue: config },\n        provideUrlLocalizer(config)\n    ];\n}\n","import { FactoryProvider, Provider } from '@angular/core';\n\nimport { UrlLocalizationConfig                          } from '../url-localization/config/url-localization-config';\nimport { provideUrlLocalization                         } from '../url-localization/config/url-localization.provider';\nimport { LanguageIntegrationConfig, LanguageIntegration } from './language-integration-config';\n\n/** Represents a factory that receives dependencies and produces the language integration configuration for an app. */\nexport type LanguageIntegrationConfigFactory = (...deps: any[]) => LanguageIntegrationConfig;\n\n/**\n * A strongly-typed factory provider for providing language integration config.\n *\n * @export\n * @interface LanguageIntegrationProvider\n * @extends {(Omit<FactoryProvider, 'provide' | 'multi'>)}\n */\nexport interface LanguageIntegrationProvider extends Omit<FactoryProvider, 'provide' | 'multi'>\n{\n    /**\n     * The factory to use for creating the language integration configuration.\n     *\n     * @type {LanguageIntegrationConfigFactory}\n     */\n    useFactory      : LanguageIntegrationConfigFactory;\n    /**\n     * (Optional) The configuration for the `UrlLocalizationService`.\n     *\n     * @type {UrlLocalizationConfig}\n     */\n    urlLocalization?: UrlLocalizationConfig;\n}\n\n/**\n * Generates language integration tokens and services to be provided in a module.\n * Used by `LanguageIntegrationModule.forRoot()`.\n *\n * @export\n * @param {LanguageIntegrationProvider} { useFactory, deps, urlLocalization } The language integration provider configuration.\n * @returns {Provider[]} An array of providers for language integration.\n */\nexport function provideLanguageIntegration({ useFactory, deps, urlLocalization }: LanguageIntegrationProvider): Provider[]\n{\n    return [\n        { provide: LanguageIntegration, useFactory, deps },\n        ...provideUrlLocalization(urlLocalization)\n    ];\n}","import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core';\n\nimport { CoreModule                                              } from '@bespunky/angular-zen/core';\nimport { LanguageIntegrationProvider, provideLanguageIntegration } from './config/language-integration.provider';\n\n/**\n * Provides services for libraries requiring integration with their user's language services.\n *\n * @export\n * @class LanguageIntegrationModule\n */\n@NgModule({\n    imports: [CoreModule]\n})\nexport class LanguageIntegrationModule\n{\n    constructor(@Optional() @SkipSelf() parentModule: LanguageIntegrationModule)\n    {\n        if (parentModule) throw new Error('`LanguageIntegrationModule` has already been loaded. Import it only once, in your app module, using `forRoot()`.');\n    }\n\n    /**\n     * Generates the language integration modules with the appropriate providers for the app to share its language services with\n     * libraries and supporting languages.\n     *\n     * @static\n     * @param {LanguageIntegrationProvider} configProvider The integration configuration. Tells the module how to operate with your language services.\n     */\n    static forRoot(configProvider: LanguageIntegrationProvider): ModuleWithProviders<LanguageIntegrationModule>\n    {\n        return {\n            ngModule : LanguageIntegrationModule,\n            providers: provideLanguageIntegration(configProvider)\n        };\n    }\n}\n","import { Directive, Injectable  } from '@angular/core';\nimport { ActivatedRoute, Router } from '@angular/router';\n\nimport { RouteAware, RouterOutletComponentBus } from '@bespunky/angular-zen/router-x';\nimport { LanguageIntegrationService           } from './language-integration.service';\n\n/**\n * Integrates with the `LanguageIntegrationService` and facilitates language related work in route-aware services.\n *\n * @export\n * @abstract\n * @class LocalizedRouteAware\n * @extends {RouteAware}\n */\n@Directive()  // Originally this was decorated with `Directive` only so angular accepts it as base for both services and components.\n@Injectable() // However, compodoc fails to collect abstract classes marked with `Directive` so I marked it as both. Tests pass, POC stackblitz doesn't show side effects.\n// eslint-disable-next-line @angular-eslint/directive-class-suffix\nexport abstract class LocalizedRouteAware extends RouteAware\n{\n    /**\n     * Creates an instance of LocalizedRouteAware.\n     * \n     * @param {LanguageIntegrationService} language The instance of the language integration service.\n     * @param {Router} router The instance of Angular's router service.\n     * @param {ActivatedRoute} route The instance of Angular's activated route service.\n     * @param {RouterOutletComponentBus} [componentBus] (Optional) The component bus for router-x functionality.\n     * Provide this when you want your route-aware service to have access to the instance(s) of the activated component(s).\n     */\n    constructor(\n        protected language     : LanguageIntegrationService,\n                  router       : Router,\n                  route        : ActivatedRoute,\n                  componentBus?: RouterOutletComponentBus\n    )\n    {\n        super(router, route, componentBus);\n        \n        if (this.language.enabled) this.initLanguageSupport();\n    }\n\n    private initLanguageSupport(): void\n    {\n        this.subscribe(this.language.ready   , this.onLanguageServicesReady.bind(this));\n        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n        this.subscribe(this.language.changed!, this.onLanguageChanged.bind(this));\n    }\n    \n    /**\n     * Called when the app's language services have initialized and are ready for use.\n     * When language integration is disabled, or no ready observable have been provided by the app\n     * this will execute immediatelly on construction time.\n     * \n     * Override to implement.\n     *\n     * @virtual\n     * @protected\n     */\n    protected onLanguageServicesReady(): void { void 0; }\n\n    /**\n     * Called when the current language used by the integrated app has changed. Override to implement.\n     * \n     * @virtual\n     * @protected\n     * @param {*} lang The language code of the new language.\n     */\n    protected onLanguageChanged(lang: string): void { void 0; }\n}\n","import { Inject, Injectable } from '@angular/core';\n\nimport { UrlReflectionService                   } from '@bespunky/angular-zen/router-x';\nimport { UrlLocalization, UrlLocalizationConfig } from '../config/url-localization-config';\nimport { UrlLocalizer                           } from '../localizers/url-localizer';\n\n/**\n * Provides tools for localization and delocalization of the currently navigated url taking into\n * account the url localization configuration provided when importing the language integration module.\n * \n * @export\n * @class UrlLocalizationService\n */\n@Injectable({ providedIn: 'root' })\nexport class UrlLocalizationService\n{\n    /**\n     * Creates an instance of UrlLocalizationService.\n     *\n     * @param {UrlLocalizationConfig} config The url localization configuration provided for the `UrlLocalization` token.\n     * @param {UrlReflectionService} urlReflection The url reflection service.\n     * @param {UrlLocalizer} localizer The url localizer which will actually do the localization work.\n     * The instance and implementation depend on the strategy configured for url localization when importing the language integration module.\n     */\n    constructor(\n        @Inject(UrlLocalization) private         config       : UrlLocalizationConfig,\n                                 private         urlReflection: UrlReflectionService,\n                                 public readonly localizer    : UrlLocalizer\n    ) { }\n    \n    /**\n     * Localizes the currently navigated url using the configured localization strategy and forces https if needed.\n     *\n     * @param {string} lang The langugae to localize the currently navigated url to.\n     * @returns {string} The localized currently navigated url.\n     */\n    public localize(lang: string): string\n    {\n        return this.replaceHttpIfRequired(this.localizer.localize(lang));\n    }\n    \n    /**\n     * Delocalizes the currently navigated url using the configured localization strategy and forces https if needed.\n     *\n     * @returns {string} The delocalized currently navigated url.\n     */\n    public delocalize(): string\n    {        \n        return this.replaceHttpIfRequired(this.localizer.delocalize());\n    }\n\n    /**\n     * Generates a localized version of the currently navigate url for each of the specified languages using the configured localization strategy.\n     * \n     * @param {string[]} langs The languages for which to generate the localized urls.\n     * @returns {{ [lang: string]: string }[]} An array of { [lang]: url } containing an object for each language and its corresponding localized url.\n     */\n    public generateLocalizedUrls(langs: string[]): { [lang: string]: string }[]\n    {\n        return langs.map(lang => ({ [lang]: this.localizer.localize(lang) }));\n    }\n\n    private replaceHttpIfRequired(url: string): string\n    {\n        return this.config?.forceHttps ? this.urlReflection.forceHttps(url) : url;\n    }\n}","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["i2.LanguageIntegrationService","i1.LanguageIntegrationService","i3","i2.UrlLocalizer"],"mappings":"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"}