diff --git a/public/compatTest.js b/public/compatTest.js index e5fd6f8d8..8b1b2a5db 100644 --- a/public/compatTest.js +++ b/public/compatTest.js @@ -8,11 +8,10 @@ function compatTest() { var hasIntl = typeof window.Intl !== 'undefined'; var hasDisplayNames = hasIntl && typeof Intl.DisplayNames !== 'undefined'; var hasPluralRules = hasIntl && typeof Intl.PluralRules !== 'undefined'; - var hasListFormat = hasIntl && typeof Intl.ListFormat !== 'undefined'; var hasNumberFormat = hasIntl && typeof Intl.NumberFormat !== 'undefined'; var isCompatible = hasPromise && hasWebSockets && hasWebCrypto && hasObjectFromEntries && hasResizeObserver - && hasCssSupports && hasDisplayNames && hasPluralRules && hasListFormat && hasNumberFormat; + && hasCssSupports && hasDisplayNames && hasPluralRules && hasNumberFormat; if (isCompatible || (window.localStorage && window.localStorage.getItem('tt-ignore-compat'))) { window.isCompatTestPassed = true; @@ -29,7 +28,6 @@ function compatTest() { console.warn('CSS.supports', hasCssSupports); console.warn('Intl.DisplayNames', hasDisplayNames); console.warn('Intl.PluralRules', hasPluralRules); - console.warn('Intl.ListFormat', hasListFormat); console.warn('Intl.NumberFormat', hasNumberFormat); } diff --git a/src/util/browser/intlListFormat.ts b/src/util/browser/intlListFormat.ts new file mode 100644 index 000000000..f3b870342 --- /dev/null +++ b/src/util/browser/intlListFormat.ts @@ -0,0 +1,5 @@ +export function getBasicListFormat() { + return { + format: (items: string[]) => items.join(', '), + }; +} diff --git a/src/util/localization/index.ts b/src/util/localization/index.ts index b91e23878..e2a533d50 100644 --- a/src/util/localization/index.ts +++ b/src/util/localization/index.ts @@ -22,6 +22,7 @@ import { DEBUG } from '../../config'; import { callApi } from '../../api/gramjs'; import renderText, { type TextFilter } from '../../components/common/helpers/renderText'; import { MAIN_IDB_STORE } from '../browser/idb'; +import { getBasicListFormat } from '../browser/intlListFormat'; import { createCallbackManager } from '../callbacks'; import readFallbackStrings from '../data/readFallbackStrings'; import { initialEstablishmentPromise, isCurrentTabMaster } from '../establishMultitabRole'; @@ -29,7 +30,7 @@ import { omit } from '../iteratees'; import { notifyLangpackUpdate } from '../multitab'; import { replaceInStringsWithTeact } from '../replaceWithTeact'; import { fastRaf } from '../schedulers'; -import { IS_MULTITAB_SUPPORTED } from '../windowEnvironment'; +import { IS_INTL_LIST_FORMAT_SUPPORTED, IS_MULTITAB_SUPPORTED } from '../windowEnvironment'; import Deferred from '../Deferred'; import LimitedMap from '../primitives/LimitedMap'; @@ -145,13 +146,18 @@ function updateLanguage(newLang: ApiLanguage) { function createFormatters() { if (!language) return; const langCode = language.pluralCode; + const listFormatFallback = getBasicListFormat(); + + function createListFormat(lang: string, type: 'conjunction' | 'disjunction') { + return IS_INTL_LIST_FORMAT_SUPPORTED ? new Intl.ListFormat(lang, { type }) : listFormatFallback; + } try { formatters = { pluralRules: new Intl.PluralRules(langCode), region: new Intl.DisplayNames(langCode, { type: 'region' }), - conjunction: new Intl.ListFormat(langCode, { type: 'conjunction' }), - disjunction: new Intl.ListFormat(langCode, { type: 'disjunction' }), + conjunction: createListFormat(langCode, 'conjunction'), + disjunction: createListFormat(langCode, 'disjunction'), number: new Intl.NumberFormat(langCode), }; } catch (e) { @@ -160,8 +166,8 @@ function createFormatters() { formatters = { pluralRules: new Intl.PluralRules(FORMATTERS_FALLBACK_LANG), region: new Intl.DisplayNames(FORMATTERS_FALLBACK_LANG, { type: 'region' }), - conjunction: new Intl.ListFormat(FORMATTERS_FALLBACK_LANG, { type: 'conjunction' }), - disjunction: new Intl.ListFormat(FORMATTERS_FALLBACK_LANG, { type: 'disjunction' }), + conjunction: createListFormat(FORMATTERS_FALLBACK_LANG, 'conjunction'), + disjunction: createListFormat(FORMATTERS_FALLBACK_LANG, 'disjunction'), number: new Intl.NumberFormat(FORMATTERS_FALLBACK_LANG), }; } diff --git a/src/util/localization/types.ts b/src/util/localization/types.ts index a9a3b3ff0..227428bc8 100644 --- a/src/util/localization/types.ts +++ b/src/util/localization/types.ts @@ -70,11 +70,13 @@ export type LangFn = { pluralCode: string; }; +type ListFormat = Pick; + export type LangFormatters = { pluralRules: Intl.PluralRules; region: Intl.DisplayNames; - conjunction: Intl.ListFormat; - disjunction: Intl.ListFormat; + conjunction: ListFormat; + disjunction: ListFormat; number: Intl.NumberFormat; }; diff --git a/src/util/windowEnvironment.ts b/src/util/windowEnvironment.ts index 542f7d827..a3c7c6d95 100644 --- a/src/util/windowEnvironment.ts +++ b/src/util/windowEnvironment.ts @@ -99,6 +99,7 @@ export const IS_INSTALL_PROMPT_SUPPORTED = 'onbeforeinstallprompt' in window; export const IS_MULTITAB_SUPPORTED = 'BroadcastChannel' in window; export const IS_OPEN_IN_NEW_TAB_SUPPORTED = IS_MULTITAB_SUPPORTED && !(IS_PWA && IS_MOBILE); export const IS_TRANSLATION_SUPPORTED = !IS_TEST; +export const IS_INTL_LIST_FORMAT_SUPPORTED = 'ListFormat' in Intl; export const MESSAGE_LIST_SENSITIVE_AREA = 750;