import { O as Optional, A as AppType } from '../types-DHs6TUPa.mjs';
import { IncomingMessage, ServerResponse } from 'http';
import { FC, PropsWithChildren } from 'react';

/**
 * Based on RFC5646: https://datatracker.ietf.org/doc/html/rfc5646
 */
type LocaleInfo = {
    /** primary language tag, like "en", "zh", "ru", affects everything in messages */
    primary: string;
    /** extended language tag, which specify language dialect like "gan" in Gan Chinese ("zh-gan"), affects almost nothing  */
    extended: Optional<string>;
    /** region tag, like "US", "CN", which usually does not affect messages itself, but number / currency formatting */
    region: Optional<string>;
    /** script tag, like "Latn", "Cyrl", which refers to used script / alphabet. Affects all messages */
    script: Optional<string>;
};
type AcceptLanguageInfo = LocaleInfo & {
    /** number in [0.0, 1.0] range to order languages by. The larger the number, the more locale is preferred */
    quality: number;
};
type LocaleSelection<AvailableLocale extends string> = {
    /** Locale from list of apps available locales, used for language selection and messages loading. Example: "en" */
    selectedLocale: AvailableLocale;
    /** Full locale, which must be passed to tools such react-intl. Can be equal sub-locale of selectedLocale or equal to it. Example: "en-GB" */
    fullLocale: string;
};
type PrefetchResult<AvailableLocale extends string, MessagesShape extends Record<string, string>> = LocaleSelection<AvailableLocale> & {
    messages: MessagesShape;
};
type SSRResult<PropsType extends Record<string, unknown>> = {
    props: PropsType;
};
type SSRResultWithI18N<AvailableLocale extends string, MessagesShape extends Record<string, string>, PropsType extends Record<string, unknown>> = {
    props: PropsType & {
        [I18N_SELECTED_LOCALE_PROP_NAME]?: AvailableLocale;
        [I18N_FULL_LOCALE_PROP_NAME]?: string;
        [I18N_MESSAGES_PROP_NAME]?: MessagesShape;
    };
};
type TranslationsContextType<AvailableLocale extends string, MessagesShape extends Record<string, string>> = {
    /**
     * Selected locale, which is used to determine, what messages set to show to user.
     * For example: "en"
     * */
    selectedLocale: AvailableLocale;
    /**
     * Original locale, from which `selectedLocale` was chosen. Sub-locale of `selectedLocale`.
     * Should be passed to tools such as `intl`, since it can contain additional info helping with number-formating and so on
     * For example: "en-GB"
     */
    fullLocale: string;
    /** Extracted messages to pass into `intl` or any similar tools  */
    messages: MessagesShape | undefined;
    /** Callback to change current language */
    switchLocale(newLocale: AvailableLocale): void;
};
/**
 * Translations helper which is used to parse / stringify locales,
 * select most suitable locale based on user preferences, load partial translations with caching and many others
 *
 * @example Init helper inside your app and re-export utils
 * import fetch from 'cross-fetch'
 * import getConfig from 'next/config'
 * import { IntlProvider as DefaultIntlProvider } from 'react-intl'
 *
 * import { TranslationsHelper } from '@open-condo/miniapp-utils/helpers/i18n'
 * import type { TranslationsProviderProps } from '@open-condo/miniapp-utils/helpers/i18n'
 *
 * import { LOCALES, DEFAULT_LOCALE } from '@/domains/common/constants/locales'
 *
 * import type { MessagesKeysType } from '@/global'
 * import type { FC, PropsWithChildren } from 'react'
 *
 * const { publicRuntimeConfig: { serviceUrl } } = getConfig()
 *
 * export type AvailableLocale = typeof LOCALES[number]
 * export type MessagesShape = Record<MessagesKeysType, string>
 *
 * const translationsAPIEndpoint = `${serviceUrl}/api/translations`
 *
 * async function loadDefaultMessages (): Promise<MessagesShape> {
 *     return (await import(`@/lang/${DEFAULT_LOCALE}.json`)).default
 * }
 *
 * async function loadMessages (locale: AvailableLocale): Promise<MessagesShape> {
 *     const response = await fetch(`${translationsAPIEndpoint}/${locale}`)
 *     if (!response.ok) throw new Error(`Could not load translations for ${locale} locale`)
 *     return response.json()
 * }
 *
 * const translationsHelper = new TranslationsHelper({
 *     locales: LOCALES,
 *     defaultLocale: DEFAULT_LOCALE,
 *     loadMessages,
 *     loadDefaultMessages,
 * })
 *
 * export type { PrefetchResult } from '@open-condo/miniapp-utils/helpers/i18n'
 *
 * export const prefetchTranslations = translationsHelper.prefetchTranslations
 * export const extractI18NInfo = translationsHelper.extractI18NInfo
 * export const useTranslationsExtractor = translationsHelper.getUseTranslationsExtractorHook()
 * export const TranslationsProvider: FC<TranslationsProviderProps<AvailableLocale, MessagesShape>> = translationsHelper.getTranslationsProvider()
 * export const useTranslations = translationsHelper.getUseTranslationsHook()
 *
 * export const IntlProvider: FC<PropsWithChildren> = ({ children }) => {
 *     const { messages, fullLocale } = useTranslations()
 *
 *     return (
 *         <DefaultIntlProvider locale={fullLocale} messages={messages}>
 *             {children}
 *         </DefaultIntlProvider>
 *     )
 * }
 *
 * @example use in _app.tsx SSR to prefetch translations
 * const translationsData = await prefetchTranslations(req, res)
 *
 * return extractI18NInfo(translationsData, {
 *     props: {},
 * })
 *
 * @example use in _app.tsx global layout to provide translations
 * const { initialSelectedLocale, initialFullLocale, initialMessages } = useTranslationsExtractor(pageProps)
 *
 * return (
 *       <TranslationsProvider
 *                 initialSelectedLocale={initialSelectedLocale}
 *                 initialFullLocale={initialFullLocale}
 *                 initialMessages={initialMessages}
 *       >
 *          <IntlProvider>
 *              {children}
 *          </IntlProvider>
 *       </TranslationsProvider>
 * )
 * */
type TranslationsProviderProps<AvailableLocale extends string, MessagesShape extends Record<string, string>> = PropsWithChildren<{
    initialSelectedLocale: AvailableLocale;
    initialFullLocale: string;
    initialMessages: MessagesShape | undefined;
}>;
type TranslationsHelperOptions<AvailableLocale extends string, MessagesShape extends Record<string, string>> = {
    locales: ReadonlyArray<AvailableLocale>;
    defaultLocale: AvailableLocale;
    loadDefaultMessages: () => Promise<MessagesShape>;
    loadMessages: (locale: AvailableLocale) => Promise<Partial<MessagesShape>>;
    localeCookieName?: string;
    localeQueryParam?: string;
};
declare const I18N_SELECTED_LOCALE_PROP_NAME = "__I18N_SELECTED_LOCALE__";
declare const I18N_FULL_LOCALE_PROP_NAME = "__I18N_FULL_LOCALE__";
declare const I18N_MESSAGES_PROP_NAME = "__I18N_MESSAGES__";
declare class TranslationsHelper<AvailableLocale extends string, MessagesShape extends Record<string, string>> {
    private readonly _locales;
    private readonly _defaultLocale;
    private _context;
    private readonly _loadMessages;
    private readonly _loadDefaultMessages;
    private readonly _translations;
    private _defaultMessages;
    readonly localeCookieName: string;
    readonly localeQueryParam: string | undefined;
    constructor(options: TranslationsHelperOptions<AvailableLocale, MessagesShape>);
    /**
     * This util parses language-defining string according to RFC5646: https://datatracker.ietf.org/doc/html/rfc5646
     * It also automatically detect and accept-language header format by enhancing result with quality info
     */
    static parseLocaleString(localeString: string): AcceptLanguageInfo;
    /**
     * Parses "Accept-Language" header value using "parseLocaleString" util and returns array of AcceptLanguageInfo
     * sorted by descending quality.
     *
     * NOTE: Empty header or non-defined header is treated as "*"
     */
    static parseAcceptLanguageHeader(headerValue: Optional<string>): Array<AcceptLanguageInfo>;
    /**
     * Generates locale-string from LocaleInfo or AcceptLanguageInfo
     */
    static toLocaleString(locale: LocaleInfo | AcceptLanguageInfo): string;
    /**
     * Enrich selected locale by scanning through requested locales
     * and finding the first one, which is sub-locale of selected one.
     * For example: selectedLocale = "en", requestedLocales: ["en-GB", "fr", "en"] -> fullLocale = "en-GB"
     * If none of requested locales is valid sub-locales, returns selectedLocale as fallback
     */
    private _getFullLocale;
    /**
     * Takes list of locales and build traverse order according to LOCALE_RESOLVE_ORDER
     * Then select first available locale from that list defaulting to defaultLocale
     * After that enhancing it with first locale, matching selected one
     *
     * @example
     * const availableLocales = ["zh", "en"] // that's what we have
     * const locales = ["zh-Hans-CN", "en-GB", "zh"] // that's what user want
     * // During function execution we build order
     * const helper = new TranslationsHelper({ locales, defaultLocale: "zh" })
     * const { selectedLocale, fullLocale } = helper.selectSupportedLocale(locales.map(TranslationsHelper.parseLocaleString))
     * // ["zh-Hans-CN", "zh-Hans", "en-GB", "en", "zh"] - resolved order
     * // selectedLocale = "en" - first match, on which we can load messages
     * // fullLocale = "en-GB" - sub-locale, providing additional info
     */
    selectSupportedLocale(locales: Array<AcceptLanguageInfo | LocaleInfo>): LocaleSelection<AvailableLocale>;
    /**
     * Obtains locale preference from query parameter (if specified), cookie, request.headers['accept-language'] or window.navigator.languages
     * and then selects supported locale using selectSupportedLocale method
     */
    getPreferredLocale(req?: Optional<IncomingMessage>, res?: Optional<ServerResponse>): LocaleSelection<AvailableLocale>;
    /**
     * Extracts prefetched translations to pageProps, so it can be available during SSR
     */
    extractI18NInfo<PropsType extends Record<string, unknown>>(translationsData: PrefetchResult<AvailableLocale, MessagesShape>, pageParams: SSRResult<PropsType>): SSRResultWithI18N<AvailableLocale, MessagesShape, PropsType>;
    getTranslations(locale: AvailableLocale): Promise<MessagesShape>;
    prefetchTranslations(req: Optional<IncomingMessage>, res: Optional<ServerResponse>): Promise<PrefetchResult<AvailableLocale, MessagesShape>>;
    getTranslationsProvider(): FC<TranslationsProviderProps<AvailableLocale, MessagesShape>>;
    getUseTranslationsExtractorHook(): <PropsType extends Record<string, unknown>>(pageProps: SSRResultWithI18N<AvailableLocale, MessagesShape, PropsType>["props"]) => {
        initialSelectedLocale: AvailableLocale;
        initialFullLocale: string;
        initialMessages: MessagesShape | undefined;
    };
    getUseTranslationsHook(): () => TranslationsContextType<AvailableLocale, MessagesShape>;
    getHOC(): <PropsType extends Record<string, unknown>, ComponentType, RouterType>(App: AppType<PropsType, ComponentType, RouterType>) => AppType<PropsType, ComponentType, RouterType>;
}

export { type AcceptLanguageInfo, type LocaleInfo, type LocaleSelection, type PrefetchResult, TranslationsHelper, type TranslationsProviderProps };
