/**
 * * [Overview](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#overview)
 * * [Setting the locale](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#locale)
 * * [Number formatting](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#number)
 * * [Date and time formatting](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#datetime)
 * * [Tips and tricks](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#tips)
 *
 * <span id="overview"></span>
 * ## Overview
 *
 * This module provides the ability to set the app locale along with date and number formatting methods and supporting utilities.
 *
 * The formatting functions [formatDate()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#formatDate), [formatNumber()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#formatNumber), and [substitute()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#substitute)
 * rely on the Internationalization APIs available in all web browsers to enable locale-sensitive date, time, and number formatting.
 *
 * <span id="locale"></span>
 * ## Setting the locale
 *
 * The SDK will automatically use locale defined via [`lang` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang) on the root `html` element, or the locale of the browser.
 * To override this behavior, you can set the locale used by the SDK with the [setLocale()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#setLocale) method.
 * This locale will determine:
 * 1. the number and date formatting used throughout the API,
 * 2. the translation of components, and
 * 3. the place label language of basemaps (if using the [basemap styles service](https://developers.arcgis.com/javascript/latest/api-reference/esri-support-BasemapStyle.html)).
 *
 * See the [localization](https://developers.arcgis.com/javascript/latest/localization/) guide page for more information.
 *
 * <span id="number"></span>
 * ## Number formatting
 *
 * You can format numbers with [formatNumber()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#formatNumber) in three different styles: `decimal`, `percent`, or `currency`.
 *
 * ```js
 *   const decimalFormatted = intl.formatNumber(12.5, {
 *     style: "decimal"
 *   });
 *
 *   const percentFormatted = intl.formatNumber(12.5, {
 *     style: "percent"
 *   });
 *
 *   const currencyFormatted = intl.formatNumber(12.5, {
 *     style: "currency",
 *     currency: "EUR",
 *     currencyDisplay: "symbol"
 *   });
 *
 *   console.log(decimalFormatted);  // In French locale: 12,5
 *   console.log(percentFormatted);  // In French locale: 1 250 %
 *   console.log(currencyFormatted); // In French locale: 12,50 €
 * ```
 *
 * By default, numbers are formatted using the appropriate set of `options` for a specified style. It is also
 * possible to control whether to use a grouping separator with a number of integer, fractional, or significant digits.
 *
 * <span id="datetime"></span>
 * ## Date and time formatting
 *
 * You can format dates with [formatDate()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#formatDate). Each date-time component of the formatted date
 * can be controlled: `weekday`, `era`, `year`, `month`, `day`, `hour`, `minute`, `second`, and `timeZoneName`.
 * The locale and region are taken into account to determine the most appropriate order of each component,
 * or whether to use 24-hour or 12-hour time formats. For example, formatting a date in `en-US` and in `en-GB` gives
 * different results.
 *
 * ```js
 * const now = Date.now();
 *
 * const dateTimeFormatOptions = {
 *   weekday: "long",
 *   day: "2-digit",
 *   month: "long",
 *   year: "numeric",
 *   hour: "numeric",
 *   minute: "numeric"
 * };
 *
 * const formatted = intl.formatDate(now, dateTimeFormatOptions);
 *
 * console.log(formatted);
 * // In English en-US: Monday, June 24, 2019, 2:28 PM
 * // In English en-GB: Monday, 24 June 2019, 14:28
 * // In French fr-FR: lundi 24 juin 2019 à 14:28
 * ```
 *
 * <span id="tips"></span>
 * ## Tips and tricks
 *
 * The [formatDate()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#formatDate), [formatNumber()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#formatNumber), and [substitute()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#substitute) functions are light wrappers
 * around the Intl APIs that cache the created [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat)
 * and [Intl.NumberFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat) formatter objects for a set of `options`.
 * Consider reusing the same `options` objects to avoid having to recreate these objects.
 *
 * ```js
 * const currencyFormatter = {
 *   style: "currency",
 *   currency: "EUR",
 *   currencyDisplay: "symbol"
 * };
 *
 * function formatCurrency(amount) {
 *   return formatNumber(amount, currencyFormatter);
 * }
 * ```
 *
 * @since 4.12
 * @see [Intl on MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl)
 * @see [Intl.DateTimeFormat on MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat)
 * @see [Intl.NumberFormat on MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat)
 * @see [FieldInfoFormat](https://developers.arcgis.com/javascript/latest/api-reference/esri-popup-support-FieldInfoFormat.html)
 * @see [Sample - Load portal items via drag and drop](https://developers.arcgis.com/javascript/latest/sample-code/portalitem-dragndrop/)
 */
import type DateTimeFieldFormat from "./layers/support/DateTimeFieldFormat.js";
import type NumberFieldFormat from "./layers/support/NumberFieldFormat.js";
import type { ResourceHandle } from "./core/Handles.js";
import type { DateFormat, DateTimeFormatOptions, TimeFormat } from "./intl/date.js";
import type { LocaleChangeCallback } from "./intl/locale.js";
import type { MessageBundle, MessageBundleLoader, MessageBundleLocale } from "./intl/messages.js";
import type { NumberFormat } from "./intl/number.js";
import type { SubstituteOptions } from "./intl/substitute.js";
import type { JSONLoaderOptions } from "./intl/t9n.js";

/**
 * Converts a [web map date format string](https://developers.arcgis.com/web-map-specification/objects/format/) to an [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat#Parameters) options object.
 *
 * @param format - A web map date format string to convert.
 * @returns The date format options derived from the format string as defined in the web map specification.
 * @see [FieldInfoFormat.dateFormat](https://developers.arcgis.com/javascript/latest/api-reference/esri-popup-support-FieldInfoFormat.html#dateFormat)
 * @example
 * const dateFormatIntlOptions = intl.convertDateFormatToIntlOptions("short-date-short-time");
 *
 * // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat#Parameters
 * // Setting the string value 'short-date-short-time' is similar to what is set in the object below
 * // dateFormatIntlOptions = {
 * //   day: "numeric",
 * //   month: "numeric",
 * //   year: "numeric",
 * //   hour: "numeric",
 * //   minute: "numeric"
 * // }
 *
 * const now = Date.now(); // 1560375191812
 * const formattedDate = intl.formatDate(now, dateFormatIntlOptions);
 *
 * console.log(formattedDate); // expected output for US English locale: "6/12/2019, 2:33 PM"
 */
export function convertDateFormatToIntlOptions(format: DateFormat | TimeFormat): Intl.DateTimeFormatOptions;

/**
 * Converts a [DateTimeFieldFormat](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-DateTimeFieldFormat.html) to an [Intl.DateTimeFormatOptions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat#Parameters) options object.
 *
 * @param format - The [DateTimeFieldFormat](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-DateTimeFieldFormat.html) to convert.
 * @returns The [Intl date format](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat#Parameters) options.
 * @since 4.34
 * @see [FieldInfo.fieldFormat](https://developers.arcgis.com/javascript/latest/api-reference/esri-popup-FieldInfo.html#fieldFormat)
 * @example
 * const dateTimeFieldFormat = new DateTimeFieldFormat({
 *   dateStyle: "short",
 *   timeStyle: "short",
 *   hour12: "always"
 * });
 * const dateTimeFieldFormatIntlOptions = intl.convertDateTimeFieldFormatToIntlOptions(dateTimeFieldFormat);
 * const now = Date.now(); // 1759292167543
 * const formattedDateTime = intl.formatDate(now, dateTimeFieldFormatIntlOptions);
 * console.log(formattedDateTime); // expected output for US English locale: "9/30/25, 9:16 PM"
 */
export function convertDateTimeFieldFormatToIntlOptions(format: DateTimeFieldFormat): Intl.DateTimeFormatOptions;

/**
 * Converts a [NumberFieldFormat](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-NumberFieldFormat.html) to an [Intl.NumberFormatOptions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat#Parameters) options object.
 *
 * @param format - The [NumberFieldFormat](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-NumberFieldFormat.html) to convert.
 * @returns The [Intl number format](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat#Parameters) options.
 * @since 4.34
 * @see [FieldInfo.fieldFormat](https://developers.arcgis.com/javascript/latest/api-reference/esri-popup-FieldInfo.html#fieldFormat)
 * @example
 * const numberFieldFormat = new NumberFieldFormat({
 *   useGrouping: "always",
 *   minimumFractionDigits: 2,
 *   maximumFractionDigits: 2
 * });
 * const numberFieldFormatIntlOptions = intl.convertNumberFieldFormatToIntlOptions(numberFieldFormat);
 * const number = 123456.789;
 * const formattedNumber = intl.formatNumber(number, numberFieldFormatIntlOptions);
 * console.log(formattedNumber); // expected output for English locale: 123,456.79
 */
export function convertNumberFieldFormatToIntlOptions(format: NumberFieldFormat): Intl.NumberFormatOptions;

/**
 * Converts a [NumberFormat](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl-number.html#NumberFormat) to an [Intl.NumberFormatOptions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat#Parameters) object.
 *
 * @param format - The [NumberFormat](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl-number.html#NumberFormat) to convert.
 * @returns The [Intl number format](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat#Parameters) options.
 * @see [FieldInfoFormat](https://developers.arcgis.com/javascript/latest/api-reference/esri-popup-support-FieldInfoFormat.html)
 * @example
 * const numberFormatIntlOptions = intl.convertNumberFormatToIntlOptions({
 *   places: 2,
 *   digitSeparator: true
 * });
 *
 * // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat#Parameters
 * // Setting the places and digitSeparator above is similar to what is set below
 * // numberFormatIntlOptions = {
 * //   useGrouping: true,
 * //   minimumFractionDigits: 2,
 * //   maximumFractionDigits: 2
 * // }
 *
 * const number = 123456.789;
 * const formattedNumber = intl.formatNumber(number, numberFormatIntlOptions);
 * console.log(formattedNumber); // expected output for English locale: 123,456.79
 */
export function convertNumberFormatToIntlOptions(format?: NumberFormat): Intl.NumberFormatOptions;

/**
 * Creates a message bundle loader specialized in loading translation files as JSON files.
 * Internally, this is the loader used to load locales by the ArcGIS Maps SDK for JavaScript.
 *
 * @param params - The configuration of the loader.
 * @returns loader - A message bundle loader.
 * @since 4.18
 * @see [fetchMessageBundle()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#fetchMessageBundle)
 * @see [registerMessageBundleLoader()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#registerMessageBundleLoader)
 * @example
 * // Assume the following directory structure
 * src/
 *   assets/
 *     translations/
 *       MyBundle.json
 *       MyBundle_fr.json
 *   widgets/
 *     MyWidget.ts
 *
 * // Configure the message bundle loader given the directory structure noted above
 *
 * const loader = intl.createJSONLoader({
 *   pattern: "my-application/", // The pattern is used to match the string in `intl.fetchMessageBundle("my-application/translations/MyBundle")`
 *   base: "my-application", // This removes the base, ie. "translations/MyBundle"
 *   location: new Url("./assets/", window.location.href) // Add the location, ie. "assets/translations/MyBundle"
 * });
 *
 * // This loads file, "./assets/translations/MyBundle.json" or
 * // "./assets/translations/MyBundle_en.json" (unless locale is updated to something, e.g. like `fr`).
 *
 * // Register the message bundle created from the createJSONLoader method
 * intl.registerMessageBundleLoader(loader);
 *
 * // Fetches the message bundle, "./assets/translations/MyBundle.json"
 * const bundle = await intl.fetchMessageBundle("my-application/MyBundle");
 *
 * // If no `base` property is specified for the loader method, the assets would read as,
 * src/
 *   assets/
 *     my-application/
 *       translations/
 *         MyBundle.json
 *         MyBundle_en.json
 *         MyBundle_fr.json
 *
 * // The method would load file, "./assets/my-application/translations/MyBundle.json" or
 * // "./assets/my-application/translations/MyBundle_en.json" (unless locale is updated to something, e.g. like `fr`).
 */
export function createJSONLoader(params: JSONLoaderOptions): MessageBundle;

/**
 * Loads a localized message bundle used with the current API locale. A message bundle is an object
 * containing translations and can be stored as a file on disk, or as an object within code. Internally,
 * the ArcGIS Maps SDK for JavaScript uses JSON files containing localized
 * translations. These bundles are identified by a unique string, ie. `bundleId`.
 *
 * The `fetchMessageBundle` method should be used if functions are working with translated strings outside of a widget.
 * Whereas, if a [Widget](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Widget.html) needs to utilize a message bundle, it should do so via the
 * [@messageBundle](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-support-widget.html#messageBundle) decorator.
 *
 * The `fetchMessageBundle` method words by finding the first loader with a `pattern` that matches the message
 * identifier. It then calls the loader's own [FetchMessageBundle](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl-messages.html#FetchMessageBundle) function.
 * If the returned Promise rejects, `fetchMessageBundle` finds another loader and repeats the operation
 * until a loader successfully fetches a bundle, or no more loaders are available.
 *
 * Below is an example of the JSON message bundle used for the [Home](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Home.html)
 * widget localized for US English locale.
 * Below that is a bundle translated for France's French locale for the same widget's strings.
 *
 * @param bundleId - The identifier of the message bundle, passed to the loader registered with [registerMessageBundleLoader()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#registerMessageBundleLoader).
 * @returns When resolved, an object containing the localized message strings.
 * @since 4.18
 * @see [registerMessageBundleLoader()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#registerMessageBundleLoader)
 * @see [@messageBundle](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-support-widget.html#messageBundle)
 * @example
 * // This snippet shows the JSON message bundle used for the Home widget in English
 * {
 *   "widgetLabel": "Home",
 *   "button": "Home",
 *   "title": "Default map view"
 * }
 * @example
 * // This snippet shows the same translation strings in the French locale
 * {
 *   "widgetLabel": "Accueil",
 *   "button": "Accueil",
 *   "title": "Vue cartographique par défaut"
 * }
 * @example
 * // Fetches the message bundle from the specified location
 * const bundle = await intl.fetchMessageBundle("my-application/MyBundle");
 * // English message bundle is loaded
 *
 * // If needing to update or set locale, call setLocale
 * intl.setLocale("fr");
 *
 * // Once locale is updated, fetch the new French message bundle
 * const bundle = await intl.fetchMessageBundle("my-application/MyBundle");
 */
export function fetchMessageBundle(bundleId: string): Promise<MessageBundle>;

/**
 * Formats a `Date` or `Number` value to a string in the current locale.
 *
 * > [!WARNING]
 * >
 * > Internally `formatDate` creates [Intl formatter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl) instances for the current locale.
 * > The formatters are cached using their `options` as a cache key.
 * > Reuse the same `options` objects for best performance.
 *
 * @param value - The [Date](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) object, or the number of milliseconds elapsed since January 1, 1970 00:00:00 UTC, to be formatted.
 * @param options - Date format options.
 * @returns Formatted string for the input Date value.
 * @see [FieldInfoFormat.dateFormat](https://developers.arcgis.com/javascript/latest/api-reference/esri-popup-support-FieldInfoFormat.html#dateFormat)
 * @example
 * const now = Date.now(); // 1560375191812
 * const dateFormatIntlOptions = intl.convertDateFormatToIntlOptions("short-date-short-time");
 *
 * const formattedDate = intl.formatDate(now, dateFormatIntlOptions);
 *
 * console.log(formattedDate); // expected output for English locale: "6/12/2019, 2:33 PM"
 */
export function formatDate(value: number | Date | undefined, options?: DateTimeFormatOptions): string;

/**
 * Formats a `date-only` field value to a string in the current locale.
 *
 * > [!WARNING]
 * >
 * > Internally `formatDateOnly` creates [Intl formatter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl) instances for the current locale.
 * > The formatters are cached using their `options` as a cache key.
 * > Reuse the same `options` objects for best performance.
 *
 * @param value - The `date-only` field value.
 * @param options - Date format options.
 * @returns Formatted string for the input `date-only` value.
 * @since 4.28
 * @example
 * // Examples of formatting "1959-10-13" on an device set to locale "en-us".
 * console.log(intl.formatDateOnly("1959-10-13"));        // 10/13/1959
 * console.log(intl.formatDateOnly("1959-10-13",
 *   intl.convertDateFormatToIntlOptions("short-date"))); // 10/13/1959
 * console.log(intl.formatDateOnly("1959-10-13",
 *   intl.convertDateFormatToIntlOptions("long-date"));   // Tuesday, October 13, 1959
 */
export function formatDateOnly(value: string, options?: Intl.DateTimeFormatOptions): string;

/**
 * Formats a `Number` value to a string in the current locale.
 *
 * > [!WARNING]
 * >
 * > Internally `formatNumber` creates [Intl formatter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl) instances for the current locale.
 * > The formatters are cached using their `options` as a cache key.
 * > Reuse the same `options` objects for best performance.
 *
 * @param value - Number to be formatted.
 * @param options - Number format options.
 * @returns Formatted string for the input Number.
 * @example
 * // Formats a number with a fixed number of places using a digit separator
 * const numberFormatIntlOptions = intl.convertNumberFormatToIntlOptions({
 *   places: 2,
 *   digitSeparator: true
 * });
 *
 * const number = 123456.789;
 * const formattedNumber = intl.formatNumber(123456.789, numberFormatIntlOptions);
 * console.log(formattedNumber); // In US English locale: 123,456.79
 * @example
 * // Formats a number as currency, in Euros
 * const amount = 14;
 * const formattedNumber = intl.formatNumber(amount, {
 *   style: "currency",
 *   currency: "EUR",
 *   currencyDisplay: "symbol"
 * });
 * console.log(formattedNumber); // In for US English locale: €14.00
 * @example
 * // Formats a number as percentage
 * const growth = 0.5;
 * const formattedNumber = intl.formatNumber(growth, {
 *   style: "percent"
 * });
 * console.log(formattedNumber); // In for US English locale: 50%
 */
export function formatNumber(value: number, options?: Intl.NumberFormatOptions): string;

/**
 * Formats a `time-only` field value to a string in the current locale.
 *
 * > [!WARNING]
 * >
 * > Internally `formatTimeOnly` creates [Intl formatter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl) instances for the current locale.
 * > The formatters are cached using their `options` as a cache key.
 * > Reuse the same `options` objects for best performance.
 *
 * @param value - The `time-only` field value.
 * @param options - Time format options.
 * @returns Formatted string for the input `time-only` value.
 * @since 4.28
 * @example
 * // Examples of formatting "13:10:39" on an device set to locale "en-us".
 * console.log(intl.formatTimeOnly("13:10:39"));          // 1:10 PM
 * console.log(intl.formatTimeOnly("13:10:39",
 *   intl.convertDateFormatToIntlOptions("short-time"));  // 1:10 PM
 * console.log(intl.formatTimeOnly("13:10:39",
 *   intl.convertDateFormatToIntlOptions("long-time"));   // 1:10:39 PM
 */
export function formatTimeOnly(value: string, options?: Intl.DateTimeFormatOptions): string;

/**
 * Formats a `timestamp-offset` field value to a string in the current locale.
 *
 * > [!WARNING]
 * >
 * > Internally `formatTimestamp` creates [Intl formatter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl) instances for the current locale.
 * > The formatters are cached using their `options` as a cache key.
 * > Reuse the same `options` objects for best performance.
 *
 * @param value - The `timestamp-offset` field value.
 * @param options - Timestamp format options.
 * @returns Formatted string for the input `timestamp-offset` value.
 * @since 4.28
 * @example
 * console.log(intl.formatDateOnly("1959-10-13")); // output - 10/13/1959
 * console.log(intl.formatDateOnly("1959-10-13", intl.convertDateFormatToIntlOptions("long-date"));
 */
export function formatTimestamp(value: string, options?: DateTimeFormatOptions): string;

/**
 * Returns the current locale used by the API. The API reads this information in a specified
 * order. This order is described as follows:
 *
 *  1. What is initialized using the global `esriConfig` variable, which also initializes the `esri/config` module.
 *  1. The [`lang` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang) defined on the root `html` element.
 *  1. What is set [`navigator.language`](https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/language), the locale defined by the web browser's user's preferences.
 *
 * The preferred way of setting a locale is via the [`lang` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang) on the root `html` element.
 * A callback can be invoked to notify when the locale changes by using [onLocaleChange()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#onLocaleChange).
 *
 * @returns The current locale string.
 * @since 4.16
 * @see [NavigatorLanguage on MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage)
 * @see [setLocale()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#setLocale)
 * @see [onLocaleChange()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#onLocaleChange)
 */
export function getLocale(): string;

/**
 * This function returns the language code associated with the current locale.
 *
 * @returns The language code of the locale (if defined).
 * @since 4.34
 * @see [W3C | Language tags in HTML and XML](https://www.w3.org/International/articles/language-tags/)
 * @see [Wikipedia | IETF language tag](https://en.wikipedia.org/wiki/IETF_language_tag)
 * @example console.log(intl.getLocaleLanguage()); // "ar"
 */
export function getLocaleLanguage(): string | null | undefined;

/**
 * Returns one of the known message bundle locale for an input locale.
 * For example, the known message bundle locale for `"fr-FR"` is `"fr"`.
 *
 * The following set of locales are available:
 * `ar`, `bs`, `ca`, `cs`, `da`, `de`, `el`, `en`, `es`, `et`, `fi`, `fr`, `he`,
 * `hr`, `hu`, `id`, `it`, `ja`, `ko`, `lt`, `lv`, `no`, `nl`, `pl`, `pt-BR`,
 * `pt-PT`, `ro`, `ru`, `sk`, `sl`, `sr`, `sv`, `th`, `tr`, `uk`, `vi`, `zh-CN`, `zh-HK`, and
 * `zh-TW`.
 *
 * @param locale - Any locale string.
 * @returns The normalized locale, or null if no known locale was found.
 * @since 4.18
 * @example
 * // For example: `en-US`
 * let locale = intl.getLocale();
 * // locale is now `en`
 * locale = intl.normalizeMessageBundleLocale(locale);
 */
export function normalizeMessageBundleLocale(locale: string): null | undefined | MessageBundleLocale;

/**
 * Registers a [callback](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl-locale.html#LocaleChangeCallback) that gets notified when
 * the locale changes. This happens when [setLocale()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#setLocale) is called, or when the web
 * browser locale changes by the user and the current locale is equal to that of the web browser.
 *
 * @param callback - A function that is fired when the locale changes.
 * It is called with the newly-set locale after executing the [setLocale()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#setLocale) method.
 * @returns Returns a handler with a `remove()` method
 * that can be called to remove the callback and stop listening for locale changes.
 * @since 4.16
 * @see [getLocale()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#getLocale)
 * @see [setLocale()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#setLocale)
 * @example
 * // Initially fetches the message bundle in the current language.
 * let bundle = await intl.fetchMessageBundle("my-application/MyBundle");
 * // Do something with the bundle
 *
 * // Set the locale to French
 * intl.setLocale("fr");
 *
 * // Listen for when locale is changed and then fetch the updated French message bundle
 * intl.onLocaleChange(function(locale) {
 *   console.log("locale changed to: ", locale);
 *   let bundle = await intl.fetchMessageBundle("my-application/MyBundle");
 * });
 */
export function onLocaleChange(callback: LocaleChangeCallback): ResourceHandle;

/**
 * Provides right-to-left preference for input locale.
 *
 * @param locale - The locale string to obtain the right-to-left information.
 * The current locale is used by default.
 * @returns Returns `true` if right-to-left is preferred for the input `locale`.
 * For example, this returns `true` if the locale is `ar` or `he`.
 * @since 4.16
 */
export function prefersRTL(locale?: string): boolean;

/**
 * Registers a message loader to load specified message bundles needed for translating strings.
 * This method needs to be called prior to fetching the application's message bundle(s).
 *
 * There are two options for creating the required
 * [MessageBundleLoader](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl-messages.html#MessageBundleLoader) param.
 *  1. Define your own loader by implementing a [MessageBundleLoader](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl-messages.html#MessageBundleLoader), or
 *  2. Use the loader the API implements via the convenience method, [createJSONLoader()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#createJSONLoader).
 *
 * Examples for both are provided below.
 *
 * @param loader - A message bundle loader.
 * @returns Returns a handler with a `remove()` method that should be called to unregister the message loader.
 *
 * Property | Type | Description
 * ------------|--------|----------------
 * remove | Function | When called, unregisters the message loader.
 * @since 4.18
 * @see [fetchMessageBundle()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#fetchMessageBundle)
 * @see [registerMessageBundleLoader()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#registerMessageBundleLoader)
 * @see [normalizeMessageBundleLocale()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#normalizeMessageBundleLocale)
 * @see [@messageBundle](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-support-widget.html#messageBundle)
 * @see [MessageBundleLoader](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl-messages.html#MessageBundleLoader)
 * @see [createJSONLoader()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#createJSONLoader)
 * @example
 * // This example defines a loader by implementing a MessageBundleLoader.
 *
 * // Register a loader that loads bundles with the specified bundle identifier
 * // starting with "my-application\/"
 *
 * const patternBundle = /^my-application\/(.+)/g;
 *
 * intl.registerMessageBundleLoader({
 *   pattern: patternBundle,
 *   // Calls the FetchMessageBundle function of the loader, passing in the bundle identifier and locale
 *   async fetchMessageBundle(bundleId, locale) {
 *     // extract the filename from the bundle id.
 *     const filename = pattern.exec(bundleId)[1];
 *     // normalize the locale, e.g. 'fr-FR' > 'fr'
 *     const knownLocale = intl.normalizeMessageBundleLocale(locale);
 *     // Fetch the corresponding JSON file given the specified url path
 *     const response = await fetch(new Url(`./assets/translations/${filename}_${knownLocale}.json`, window.location.href));
 *     return response.json();
 *   }
 * });
 *
 * // If the locale changes, calling fetchMessageBundle resolves to the new localized message bundle.
 * intl.onLocaleChange((newLocale) => {
 *   const bundle = await intl.fetchMessageBundle("my-application/translations/MyBundle");
 *   // loads file: "https://myserver/my-application/translations/MyBundle_fr.json"
 * });
 *
 * // Updates the locale
 * intl.setLocale("fr");
 * @example
 * // This example defines the loader via the createJSONLoader method.
 *
 * // Register a loader that loads bundles with the specified bundle identifier
 * // starting with "my-application\/"
 *
 * const patternBundle = /^my-application\/(.+)/g;
 *
 * intl.registerMessageBundleLoader(
 *   intl.createJSONLoader({
 *     pattern: patternBundle,
 *     base: "my-application/",
 *     location: new URL("./assets/", window.location.href)
 *   })
 * );
 *
 * // If the locale changes, calling fetchMessageBundle resolves to the new localized message bundle.
 * intl.onLocaleChange((newLocale) => {
 *   const bundle = await intl.fetchMessageBundle("my-application/MyBundle");
 *  // loads file: "https://myserver/my-application/MyBundle_fr.json"
 * });
 *
 * // Updates the locale
 * intl.setLocale("fr");
 */
export function registerMessageBundleLoader(loader: MessageBundleLoader): ResourceHandle;

/**
 * Sets the locale used by the SDK.
 * Prefer setting the [`lang` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang) on the root `html` element.
 *
 * When the locale changes, the registered callback for [onLocaleChange()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#onLocaleChange) is called.
 *
 * > [!WARNING]
 * >
 * > The JavaScript SDK reacts when the locale changes at runtime.
 * > Please note that this is considered experimental.
 *
 * The JavaScript SDK offers the same level of support for [number](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#formatNumber), and [date](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#formatDate) formatting
 * as web browsers' Intl APIs.
 * For string translations, the following set of locales are available:
 * `ar`, `bg`, `bs`, `ca`, `cs`, `da`, `de`, `el`, `en`, `es`, `et`, `fi`, `fr`,
 * `he`, `hr`, `hu`, `id`, `it`, `ja`, `ko`, `lt`, `lv`, `no`, `nl`, `pl`, `pt-BR`,
 * `pt-PT`, `ro`, `ru`, `sk`, `sl`, `sr`, `sv`, `th`, `tr`, `uk`, `vi`, `zh-CN`, `zh-HK`, and
 * `zh-TW`.
 *
 * If translation messages are not available for the current locale, the language is determined
 * based on the order as described in [getLocale()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#getLocale); or else it defaults to English messages.
 *
 * It is possible to set the locale to be more specific such as `en-AU` or `fr-CA`.
 * The strings will still be translated using `en` messages (which use American English),
 * while dates, times, and numbers use the more specific data and number formatting.
 * Read more in [Locale fallback](https://developers.arcgis.com/javascript/latest/localization/#locale-fallback).
 *
 * @param locale - The new Unicode locale identifier string, similar to the Intl APIs.
 *   If this is `undefined`, the locale is reset to its default value described in [getLocale()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#getLocale).
 * @since 4.16
 * @see [More info on locale on MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_identification_and_negotiation)
 * @see [getLocale()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#getLocale)
 * @see [onLocaleChange()](https://developers.arcgis.com/javascript/latest/api-reference/esri-intl.html#onLocaleChange)
 * @example
 * // Sets the locale to French
 * intl.setLocale("fr");
 *
 * // Sets the locale to UK English.
 * // Dates are formatted in day/month/year order.
 * intl.setLocale("en-GB");
 *
 * // Sets the locale to US English.
 * // Dates are formatted in month/day/year order.
 * intl.setLocale("en-US");
 */
export function setLocale(locale: string | null | undefined): void;

/**
 * Use this to substitute keys in a `template` string with values from the argument `data`.
 * `null` or `undefined` values aren't printed in the output result.
 *
 * The formatting of the values from `data` can be specified.
 * By default the values will be formatted based on their native JavaScript type.
 *
 * > [!WARNING]
 * >
 * > Internally `substitute` creates [Intl formatter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl) instances for the current locale.
 * > The formatters are cached using the `options` as a cache key.
 * > Reuse the same `options` objects for best performance.
 *
 * @param template - Template string to use for substitution.
 * @param data - Data object to be substituted.
 * @param options - Options for determining how to substitute keys in the template string.
 * @returns The formatted string.
 * @see [Sample - Load portal items via drag and drop](https://developers.arcgis.com/javascript/latest/sample-code/portalitem-dragndrop/)
 * @example
 * // Format a date
 * const data = {
 *   increasedValue: 500,
 *   time: Date.UTC(2019),
 * }
 *
 * const dateFormatOptions = intl.convertDateFormatToIntlOptions("short-date-short-time-24");
 *
 * intl.substitute("Date: {time}", data, {
 *   format: {
 *     time: {
 *       type: "date",
 *       intlOptions: dateFormatOptions
 *     }
 *   }
 * });
 * @example
 * // Format a number
 * const data = {
 *   increasedValue: 500,
 *   time: Date.UTC(2019),
 * }
 *
 * intl.substitute("Number: {value}", data, {
 *   format: {
 *     value: {
 *       type: "number",
 *       intlOptions: {
 *         maximumFractionDigits: 21
 *       }
 *     }
 *   }
 * });
 * @example
 * const data = {
 *   increasedValue: 500,
 *   time: Date.UTC(2019),
 * }
 *
 * intl.substitute("Median income increased by {increasedValue} in {time:yearFormat}", data, {
 *   format: {
 *     increasedValue: {
 *       type: "number",
 *       intlOptions: {
 *         useGrouping: true,
 *         currency: "EUR",
 *         currencyDisplay: "symbol",
 *         maximumFractionDigits: 2
 *       }
 *     },
 *     yearFormat: {
 *       type: "date",
 *       intlOptions: {
 *         year: "numeric"
 *       }
 *     }
 *   }
 * });
 */
export function substitute(template: string, data: Record<string, any>, options?: SubstituteOptions): string;