diff --git a/about_preload.js b/about_preload.js
index 731ff819167297e7d3eb79ae0dc9fecec01b44ca..23620701ef490a8de7a390c638ec1577084c4cc1 100644
--- a/about_preload.js
+++ b/about_preload.js
@@ -7,11 +7,11 @@ const os = require('os');
 const { setupI18n } = require('./ts/util/i18n/i18n');
 
 const config = url.parse(window.location.toString(), true).query;
-const { dictionary, locale } = ipcRenderer.sendSync('locale-data');
+const { dictionary, crowdinLocale } = ipcRenderer.sendSync('locale-data');
 
 window.theme = config.theme;
 window.i18n = setupI18n({
-  locale,
+  crowdinLocale,
   translationDictionary: dictionary,
 });
 
diff --git a/password_preload.js b/password_preload.js
index cd88b580a855cf9c50a037d72b47a13eb3d31e4c..d8dac4ad3be9f8fc77f7c848e8c272b9d6ae73e5 100644
--- a/password_preload.js
+++ b/password_preload.js
@@ -6,13 +6,14 @@ const url = require('url');
 const { setupI18n } = require('./ts/util/i18n/i18n');
 
 const config = url.parse(window.location.toString(), true).query;
-const { dictionary, locale } = ipcRenderer.sendSync('locale-data');
+const { dictionary, crowdinLocale } = ipcRenderer.sendSync('locale-data');
 
 // If the app is locked we can't access the database to check the theme.
 window.theme = 'classic-dark';
 window.primaryColor = 'green';
+
 window.i18n = setupI18n({
-  locale,
+  crowdinLocale,
   translationDictionary: dictionary,
 });
 
diff --git a/preload.js b/preload.js
index eefd06f5848eb3941850a5cb65169363eff76129..fc5d6ea95723c88dc8f7c55c81a02d30397cde4e 100644
--- a/preload.js
+++ b/preload.js
@@ -11,12 +11,12 @@ const _ = require('lodash');
 
 const { setupI18n } = require('./ts/util/i18n/i18n');
 
-const { dictionary, locale } = ipc.sendSync('locale-data');
+const { dictionary, crowdinLocale } = ipc.sendSync('locale-data');
 
 const config = url.parse(window.location.toString(), true).query;
 const configAny = config;
 
-window.i18n = setupI18n({ locale, translationDictionary: dictionary });
+window.i18n = setupI18n({ crowdinLocale, translationDictionary: dictionary });
 
 let title = config.name;
 if (config.environment !== 'production') {
diff --git a/ts/components/dialog/OnionStatusPathDialog.tsx b/ts/components/dialog/OnionStatusPathDialog.tsx
index 94232acd73322c70963e281a270311fac1b945e6..2221f24245aae50163e965f5d71bd74fea086596 100644
--- a/ts/components/dialog/OnionStatusPathDialog.tsx
+++ b/ts/components/dialog/OnionStatusPathDialog.tsx
@@ -22,7 +22,7 @@ import { THEME_GLOBALS } from '../../themes/globals';
 import { SessionWrapperModal } from '../SessionWrapperModal';
 import { SessionIcon, SessionIconButton } from '../icon';
 import { SessionSpinner } from '../loading';
-import { getLocale } from '../../util/i18n/shared';
+import { getCrowdinLocale } from '../../util/i18n/shared';
 
 export type StatusLightType = {
   glowStartDelay: number;
@@ -136,9 +136,9 @@ const OnionPathModalInner = () => {
           <Flex container={true} flexDirection="column" alignItems="flex-start">
             {nodes.map((snode: Snode | any) => {
               const country = reader?.get(snode.ip || '0.0.0.0')?.country;
-              const locale = getLocale();
+              const locale = getCrowdinLocale();
 
-              // typescript complains that the [] operator cannot be used with the 'string' coming from getLocale()
+              // typescript complains that the [] operator cannot be used with the 'string' coming from getCrowdinLocale()
               const countryNamesAsAny = country?.names as any;
               const countryName =
                 snode.label || // to take care of the "Device" case
diff --git a/ts/localization/constants.ts b/ts/localization/constants.ts
index 9f24a241d1a8856d20776e714289b3beda0433af..ed798063e257e3fa920dba30c8333c08dd220df6 100644
--- a/ts/localization/constants.ts
+++ b/ts/localization/constants.ts
@@ -6,3 +6,89 @@ export enum LOCALE_DEFAULTS {
 }
 
 export const rtlLocales = ['ar', 'fa', 'he', 'ps', 'ur'];
+
+export const crowdinLocales = [
+  'en',
+  'af',
+  'ar',
+  'az',
+  'bal',
+  'be',
+  'bg',
+  'bn',
+  'ca',
+  'cs',
+  'cy',
+  'da',
+  'de',
+  'el',
+  'eo',
+  'es-419',
+  'es',
+  'et',
+  'eu',
+  'fa',
+  'fi',
+  'fil',
+  'fr',
+  'gl',
+  'ha',
+  'he',
+  'hi',
+  'hr',
+  'hu',
+  'hy-AM',
+  'id',
+  'it',
+  'ja',
+  'ka',
+  'km',
+  'kmr',
+  'kn',
+  'ko',
+  'ku',
+  'lg',
+  'lo',
+  'lt',
+  'lv',
+  'mk',
+  'mn',
+  'ms',
+  'my',
+  'nb',
+  'ne',
+  'nl',
+  'nn',
+  'no',
+  'ny',
+  'pa',
+  'pl',
+  'ps',
+  'pt-BR',
+  'pt-PT',
+  'ro',
+  'ru',
+  'sh',
+  'si',
+  'sk',
+  'sl',
+  'sq',
+  'sr',
+  'sr',
+  'sv',
+  'sw',
+  'ta',
+  'te',
+  'th',
+  'tl',
+  'tr',
+  'uk',
+  'ur',
+  'uz',
+  'vi',
+  'xh',
+  'zh-CN',
+  'zh-TW',
+] as const;
+
+export type CrowdinLocale = (typeof crowdinLocales)[number];
diff --git a/ts/mains/main_node.ts b/ts/mains/main_node.ts
index ecc87816a01013a52f9a5f545aa0e7449761e375..3de0572514d5e7d4dbc857e72e33c47fd041a614 100644
--- a/ts/mains/main_node.ts
+++ b/ts/mains/main_node.ts
@@ -162,8 +162,12 @@ import { setLatestRelease } from '../node/latest_desktop_release';
 import { isDevProd, isTestIntegration } from '../shared/env_vars';
 import { classicDark } from '../themes';
 import type { SetupI18nReturnType } from '../types/localizer';
-import { getTranslationDictionary } from '../util/i18n/shared';
-import { getLocale, isLocaleSet, type Locale } from '../util/i18n/shared';
+
+import {
+  isSessionLocaleSet,
+  getTranslationDictionary,
+  getCrowdinLocale,
+} from '../util/i18n/shared';
 import { loadLocalizedDictionary } from '../node/locale';
 
 // Both of these will be set after app fires the 'ready' event
@@ -184,7 +188,7 @@ function prepareURL(pathSegments: Array<string>, moreKeys?: { theme: any }) {
     slashes: true,
     query: {
       name: packageJson.productName,
-      locale: getLocale(),
+      locale: getCrowdinLocale(),
       version: app.getVersion(),
       commitHash: config.get('commitHash'),
       environment: (config as any).environment,
@@ -717,11 +721,12 @@ app.on('ready', async () => {
   logger = getLogger();
   assertLogger().info('app ready');
   assertLogger().info(`starting version ${packageJson.version}`);
-  if (!isLocaleSet()) {
-    const appLocale = (process.env.LANGUAGE || app.getLocale() || 'en') as Locale;
+  if (!isSessionLocaleSet()) {
+    const appLocale = process.env.LANGUAGE || app.getLocale() || 'en';
     const loadedLocale = loadLocalizedDictionary({ appLocale, logger });
     i18n = loadedLocale.i18n;
-    assertLogger().info(`locale is ${loadedLocale.locale}`);
+    assertLogger().info(`appLocale is ${appLocale}`);
+    assertLogger().info(`crowdin locale is ${loadedLocale.crowdinLocale}`);
   }
 
   const key = getDefaultSQLKey();
@@ -907,7 +912,7 @@ ipc.on('locale-data', event => {
   // eslint-disable-next-line no-param-reassign
   event.returnValue = {
     dictionary: getTranslationDictionary(),
-    locale: getLocale(),
+    crowdinLocale: getCrowdinLocale(),
   };
 });
 
diff --git a/ts/mains/main_renderer.tsx b/ts/mains/main_renderer.tsx
index 2b68622f19ebe0c96f30000a41d942fc25d81138..30307879da08e81c586534a4c5248fc80899cbe8 100644
--- a/ts/mains/main_renderer.tsx
+++ b/ts/mains/main_renderer.tsx
@@ -29,7 +29,7 @@ import { Notifications } from '../util/notifications';
 import { Registration } from '../util/registration';
 import { Storage, isSignInByLinking } from '../util/storage';
 import { getOppositeTheme, isThemeMismatched } from '../util/theme';
-import { getLocale } from '../util/i18n/shared';
+import { getCrowdinLocale } from '../util/i18n/shared';
 import { rtlLocales } from '../localization/constants';
 
 // Globally disable drag and drop
@@ -292,7 +292,7 @@ async function start() {
   });
 
   function switchBodyToRtlIfNeeded() {
-    const loc = getLocale();
+    const loc = getCrowdinLocale();
     if (rtlLocales.includes(loc) && !document.getElementById('body')?.classList.contains('rtl')) {
       document.getElementById('body')?.classList.add('rtl');
     }
diff --git a/ts/node/locale.ts b/ts/node/locale.ts
index c33993b13a6f71c4ad9ccf8a13d697b2f2798481..7acf1527ab5124d0bb98220f35ab4736c98b10dd 100644
--- a/ts/node/locale.ts
+++ b/ts/node/locale.ts
@@ -1,12 +1,13 @@
 import fs from 'fs';
 import path from 'path';
+import { isEmpty } from 'lodash';
 import type { LocalizerDictionary, SetupI18nReturnType } from '../types/localizer';
 import { getAppRootPath } from './getRootPath';
-import type { Locale } from '../util/i18n/shared';
 import { en } from '../localization/locales';
 import { setupI18n } from '../util/i18n/i18n';
+import { CrowdinLocale } from '../localization/constants';
 
-function normalizeLocaleName(locale: string) {
+export function normalizeLocaleName(locale: string) {
   const dashedLocale = locale.replaceAll('_', '-');
 
   // Note: this is a pain, but we somehow needs to keep in sync this logic and the LOCALE_PATH_MAPPING from
@@ -46,8 +47,11 @@ function getLocaleMessages(locale: string): LocalizerDictionary {
 export function loadLocalizedDictionary({
   appLocale,
   logger,
-}: { appLocale?: Locale; logger?: any } = {}): {
-  locale: Locale;
+}: {
+  appLocale: string;
+  logger?: any;
+}): {
+  crowdinLocale: CrowdinLocale;
   i18n: SetupI18nReturnType;
 } {
   if (!appLocale) {
@@ -63,26 +67,28 @@ export function loadLocalizedDictionary({
   //
   // possible locales:
   // https://github.com/electron/electron/blob/master/docs/api/locales.md
-  let locale = normalizeLocaleName(appLocale) as Locale;
+  let crowdinLocale = normalizeLocaleName(appLocale) as CrowdinLocale;
   let translationDictionary;
 
   try {
-    translationDictionary = getLocaleMessages(locale);
+    translationDictionary = getLocaleMessages(crowdinLocale);
   } catch (e) {
-    logger.error(`Problem loading messages for locale ${locale} ${e.stack}`);
+    logger.error(`Problem loading messages for locale ${crowdinLocale} ${e.stack}`);
     logger.error('Falling back to en locale');
+  }
 
-    locale = 'en';
+  if (!translationDictionary || isEmpty(translationDictionary)) {
     translationDictionary = en;
+    crowdinLocale = 'en';
   }
 
   const i18n = setupI18n({
-    locale,
+    crowdinLocale,
     translationDictionary,
   });
 
   return {
-    locale,
+    crowdinLocale,
     i18n,
   };
 }
diff --git a/ts/node/spell_check.ts b/ts/node/spell_check.ts
index ccd0d9bcf940475ed843861eb1b5ccf1bf8e7c5d..dfd932ad8c6ff269bcb44425ce5c055a5eed4239 100644
--- a/ts/node/spell_check.ts
+++ b/ts/node/spell_check.ts
@@ -11,10 +11,11 @@ export const setup = (browserWindow: BrowserWindow, i18n: SetupI18nReturnType) =
   const userLocale = process.env.LANGUAGE
     ? process.env.LANGUAGE
     : osLocaleSync().replace(/_/g, '-');
-  const userLocales = [userLocale, userLocale.split('-')[0]];
+  const userLocales = [userLocale, userLocale.split('-')[0], userLocale.split('_')[0]];
 
   const available = session.availableSpellCheckerLanguages;
   const languages = userLocales.filter(l => available.includes(l));
+  console.log(`spellcheck: userLocales: ${userLocales}`);
   console.log(`spellcheck: user locale: ${userLocale}`);
   console.log('spellcheck: available spellchecker languages: ', available);
   console.log('spellcheck: setting languages to: ', languages);
diff --git a/ts/test/session/unit/utils/i18n/util.ts b/ts/test/session/unit/utils/i18n/util.ts
index b377b1d69cec0048c2be944612044a2ec451db01..fe9947be99ab132d2d446dda949732e98ec10d8f 100644
--- a/ts/test/session/unit/utils/i18n/util.ts
+++ b/ts/test/session/unit/utils/i18n/util.ts
@@ -12,5 +12,8 @@ export const testDictionary = {
 } as const;
 
 export function initI18n(dictionary: Record<string, string> = en) {
-  return setupI18n({ locale: 'en', translationDictionary: dictionary as LocalizerDictionary });
+  return setupI18n({
+    crowdinLocale: 'en',
+    translationDictionary: dictionary as LocalizerDictionary,
+  });
 }
diff --git a/ts/util/i18n/emojiPanelI18n.ts b/ts/util/i18n/emojiPanelI18n.ts
index ba83b4d04cbc979c6fea1dc4cb72c4b457b051a1..0c0996e1ae2ff0dede14217c8703cffda4a95641 100644
--- a/ts/util/i18n/emojiPanelI18n.ts
+++ b/ts/util/i18n/emojiPanelI18n.ts
@@ -1,4 +1,4 @@
-import { getLocale } from './shared';
+import { getCrowdinLocale } from './shared';
 
 let langNotSupportedMessageShown = false;
 
@@ -7,7 +7,7 @@ export const loadEmojiPanelI18n = async () => {
     return undefined;
   }
   const triedLocales: Array<string> = [];
-  const lang = getLocale();
+  const lang = getCrowdinLocale();
   if (lang !== 'en') {
     try {
       triedLocales.push(lang);
diff --git a/ts/util/i18n/functions/getRawMessage.ts b/ts/util/i18n/functions/getRawMessage.ts
index 69cbd2da47405a01021d623f5e593ead7bee62b7..bd04d549eb583fee851f5020e61395cc6c6994c7 100644
--- a/ts/util/i18n/functions/getRawMessage.ts
+++ b/ts/util/i18n/functions/getRawMessage.ts
@@ -8,7 +8,12 @@ import type {
   PluralKey,
   PluralString,
 } from '../../../types/localizer';
-import { getTranslationDictionary, getLocale, getStringForCardinalRule, i18nLog } from '../shared';
+import {
+  getTranslationDictionary,
+  getStringForCardinalRule,
+  i18nLog,
+  getCrowdinLocale,
+} from '../shared';
 
 function getPluralKey<R extends PluralKey | undefined>(string: PluralString): R {
   const match = /{(\w+), plural, one \[.+\] other \[.+\]}/g.exec(string);
@@ -80,7 +85,7 @@ export function getRawMessage<
       } else {
         const num = args?.[pluralKey as keyof typeof args] ?? 0;
 
-        const currentLocale = getLocale();
+        const currentLocale = getCrowdinLocale();
         const cardinalRule = new Intl.PluralRules(currentLocale).select(num);
 
         const pluralString = getStringForCardinalRule(localizedString, cardinalRule);
diff --git a/ts/util/i18n/i18n.ts b/ts/util/i18n/i18n.ts
index c7dde60fa9c8847d0720d93d7c0b3cc7165f6939..994bcfd2d77313a6c8bba4b9ae05d1c20a1bb6fa 100644
--- a/ts/util/i18n/i18n.ts
+++ b/ts/util/i18n/i18n.ts
@@ -3,35 +3,36 @@
 import { isEmpty } from 'lodash';
 import type { LocalizerDictionary, SetupI18nReturnType } from '../../types/localizer';
 import { getMessage } from './functions/getMessage';
-import { i18nLog, Locale, setInitialLocale } from './shared';
+import { i18nLog, setInitialLocale } from './shared';
+import { CrowdinLocale } from '../../localization/constants';
 
 /**
  * Sets up the i18n function with the provided locale and messages.
  *
  * @param params - An object containing optional parameters.
- * @param params.locale - The locale to use for translations
- * @param params.translationDictionary - A dictionary of localized messages. Defaults to {@link en}.
+ * @param params.crowdinLocale - The locale to use for translations (crowdin)
+ * @param params.translationDictionary - A dictionary of localized messages
  *
  * @returns A function that retrieves a localized message string, substituting variables where necessary.
  */
 export const setupI18n = ({
-  locale,
+  crowdinLocale,
   translationDictionary,
 }: {
-  locale: Locale;
+  crowdinLocale: CrowdinLocale;
   translationDictionary: LocalizerDictionary;
 }): SetupI18nReturnType => {
-  if (!locale) {
-    throw new Error(`locale not provided in i18n setup`);
+  if (!crowdinLocale) {
+    throw new Error(`crowdinLocale not provided in i18n setup`);
   }
 
   if (!translationDictionary || isEmpty(translationDictionary)) {
     throw new Error('translationDictionary was not provided');
   }
 
-  setInitialLocale(locale, translationDictionary);
+  setInitialLocale(crowdinLocale, translationDictionary);
 
-  i18nLog(`Setup Complete with locale: ${locale}`);
+  i18nLog(`Setup Complete with crowdinLocale: ${crowdinLocale}`);
 
   return getMessage;
 };
diff --git a/ts/util/i18n/localizedString.ts b/ts/util/i18n/localizedString.ts
index fc6c015956726b4c419b821819a38698dc2b1464..ed5dbc44bee03022fcfc290f6d615c19fc96fb61 100644
--- a/ts/util/i18n/localizedString.ts
+++ b/ts/util/i18n/localizedString.ts
@@ -1,10 +1,10 @@
 import { en } from '../../localization/locales';
 import {
-  getLocale,
   getStringForCardinalRule,
   getFallbackDictionary,
   getTranslationDictionary,
   i18nLog,
+  getCrowdinLocale,
 } from './shared';
 import { LOCALE_DEFAULTS } from '../../localization/constants';
 import { deSanitizeHtmlTags, sanitizeArgs } from '../../components/basic/Localizer';
@@ -236,7 +236,7 @@ export class LocalizedStringBuilder<
       }
     }
 
-    const currentLocale = getLocale();
+    const currentLocale = getCrowdinLocale();
     const cardinalRule = new Intl.PluralRules(currentLocale).select(num);
 
     let pluralString = getStringForCardinalRule(str, cardinalRule);
diff --git a/ts/util/i18n/shared.ts b/ts/util/i18n/shared.ts
index 4b6b8177aa38ffd3114e5d4bb708e5adebed0a93..353c4c2984704c52bedca7d9d63027ba897b7b22 100644
--- a/ts/util/i18n/shared.ts
+++ b/ts/util/i18n/shared.ts
@@ -1,10 +1,11 @@
+import { Locale } from 'date-fns';
+import { CrowdinLocale } from '../../localization/constants';
 import { en } from '../../localization/locales';
 import type { LocalizerDictionary } from '../../types/localizer';
 import { timeLocaleMap } from './timeLocaleMap';
 
 let mappedBrowserLocaleDisplayed = false;
-let initialLocale: Locale | undefined;
-
+let crowdinLocale: CrowdinLocale | undefined;
 let translationDictionary: LocalizerDictionary | undefined;
 
 /**
@@ -12,7 +13,7 @@ let translationDictionary: LocalizerDictionary | undefined;
  */
 export function resetLocaleAndTranslationDict() {
   translationDictionary = undefined;
-  initialLocale = undefined;
+  crowdinLocale = undefined;
 }
 
 /**
@@ -46,32 +47,34 @@ export function i18nLog(message: string) {
   }
 }
 
-export type Locale = keyof typeof timeLocaleMap;
-
 export function getTimeLocaleDictionary() {
-  return timeLocaleMap[getLocale()];
+  return (timeLocaleMap as Record<string, Locale>)[getBrowserLocale()] || timeLocaleMap.en;
 }
 
 /**
- * Returns the current locale.
+ * Returns the current locale as supported by Session (i.e. one generated by crowdin)
  */
-export function getLocale(): Locale {
-  if (!initialLocale) {
-    i18nLog(`getLocale: using initialLocale: ${initialLocale}`);
+export function getCrowdinLocale(): CrowdinLocale {
+  if (!crowdinLocale) {
+    i18nLog(`getCrowdinLocale: ${crowdinLocale}`);
 
-    throw new Error('initialLocale is unset');
+    throw new Error('crowdinLocale is unset');
   }
-  return initialLocale;
+  return crowdinLocale;
 }
 
 /**
  * Returns the closest supported locale by the browser.
  */
 export function getBrowserLocale() {
-  const userLocaleDashed = getLocale();
+  const browserLocale = process.env.LANGUAGE || getCrowdinLocale() || 'en';
+
+  // supportedLocalesOf will throw if the locales has a '_' instead of a '-' in it.
+  const userLocaleDashed = browserLocale.replaceAll('_', '-');
 
-  const matchinglocales = Intl.DateTimeFormat.supportedLocalesOf(userLocaleDashed);
-  const mappingTo = matchinglocales?.[0] || 'en';
+  const matchingLocales = Intl.DateTimeFormat.supportedLocalesOf(userLocaleDashed);
+
+  const mappingTo = matchingLocales?.[0] || 'en';
 
   if (!mappedBrowserLocaleDisplayed) {
     mappedBrowserLocaleDisplayed = true;
@@ -81,16 +84,16 @@ export function getBrowserLocale() {
   return mappingTo;
 }
 
-export function setInitialLocale(locale: Locale, dictionary: LocalizerDictionary) {
-  if (translationDictionary) {
-    throw new Error('setInitialLocale: translationDictionary or initialLocale is already init');
+export function setInitialLocale(crowdinLocaleArg: CrowdinLocale, dictionary: LocalizerDictionary) {
+  if (translationDictionary || crowdinLocale) {
+    throw new Error('setInitialLocale: translationDictionary or crowdinLocale is already init');
   }
   translationDictionary = dictionary;
-  initialLocale = locale;
+  crowdinLocale = crowdinLocaleArg;
 }
 
-export function isLocaleSet() {
-  return initialLocale !== undefined;
+export function isSessionLocaleSet() {
+  return !!crowdinLocale;
 }
 
 export function getStringForCardinalRule(
diff --git a/ts/util/i18n/timeLocaleMap.ts b/ts/util/i18n/timeLocaleMap.ts
index 89b49924825be8657f5803dd9d4f2020a76e931b..1811f83f89670810ac0f46aa8631a0ae26bcd3fb 100644
--- a/ts/util/i18n/timeLocaleMap.ts
+++ b/ts/util/i18n/timeLocaleMap.ts
@@ -1,66 +1,37 @@
-import timeLocales from 'date-fns/locale';
+import * as supportedByDateFns from 'date-fns/locale';
+
+import { Locale } from 'date-fns';
+import { CrowdinLocale, crowdinLocales } from '../../localization/constants';
+
+type MappedToEnType = { [K in CrowdinLocale]: Locale };
+
+/**
+ * Map every locales supported by Crowdin to english first.
+ * Then we overwrite those values with what we have support for from date-fns and what we need to overwrite
+ */
+const mappedToEn: MappedToEnType = crowdinLocales.reduce((acc, key) => {
+  acc[key] = supportedByDateFns.enUS;
+  return acc;
+}, {} as MappedToEnType);
 
 // Note: to find new mapping you can use:
 // https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes
 
-export const timeLocaleMap = {
-  ar: timeLocales.ar,
-  be: timeLocales.be,
-  bg: timeLocales.bg,
-  ca: timeLocales.ca,
-  cs: timeLocales.cs,
-  da: timeLocales.da,
-  de: timeLocales.de,
-  el: timeLocales.el,
-  en: timeLocales.enUS,
-  eo: timeLocales.eo,
-  es: timeLocales.es,
-  'es-419': timeLocales.es,
-  et: timeLocales.et,
-  fa: timeLocales.faIR,
-  fi: timeLocales.fi,
-  fil: timeLocales.fi,
-  fr: timeLocales.fr,
-  he: timeLocales.he,
-  hi: timeLocales.hi,
-  hr: timeLocales.hr,
-  hu: timeLocales.hu,
-  'hy-AM': timeLocales.hy,
-  id: timeLocales.id,
-  it: timeLocales.it,
-  ja: timeLocales.ja,
-  ka: timeLocales.ka,
-  km: timeLocales.km,
-  kmr: timeLocales.km, // central khmer, mapped to date-fns khmer: km
-  kn: timeLocales.kn,
-  ko: timeLocales.ko,
-  lt: timeLocales.lt,
-  lv: timeLocales.lv,
-  mk: timeLocales.mk,
-  nb: timeLocales.nb, // Norwegian Bokmål, mapped to date-fns "Norwegian Bokmål": nb
-  nl: timeLocales.nl, // dutch/flemish
-  no: timeLocales.nb, // norwegian, mapped to date-fns "Norwegian Bokmål": nb
-  pa: timeLocales.hi, // punjabi: not supported by date-fns, mapped to Hindi: hi
-  pl: timeLocales.pl,
-  'pt-BR': timeLocales.ptBR,
-  'pt-PT': timeLocales.pt,
-  ro: timeLocales.ro,
-  ru: timeLocales.ru,
-  si: timeLocales.enUS, // sinhala, not suported by date-fns, mapped to english for now
-  sk: timeLocales.sk,
-  sl: timeLocales.sl,
-  sq: timeLocales.sq,
-  sr: timeLocales.sr,
-  sv: timeLocales.sv,
-  ta: timeLocales.ta,
-  th: timeLocales.th,
-  tl: timeLocales.enUS, // tagalog, not suported by date-fns, mapped to english for now
-  tr: timeLocales.tr,
-  uk: timeLocales.uk,
-  uz: timeLocales.uz,
-  vi: timeLocales.vi,
-  'zh-CN': timeLocales.zhCN,
-  'zh-TW': timeLocales.zhTW,
+export const timeLocaleMap: Record<CrowdinLocale, Locale> = {
+  ...mappedToEn,
+  ...supportedByDateFns,
+  en: supportedByDateFns.enUS,
+
+  // then overwrite anything that we don't agree with or need to support specifically.
+  'es-419': supportedByDateFns.es,
+  fa: supportedByDateFns.faIR,
+  fil: supportedByDateFns.fi,
+  'hy-AM': supportedByDateFns.hy,
+  kmr: supportedByDateFns.km, // Central khmer
+  'pt-BR': supportedByDateFns.ptBR,
+  'pt-PT': supportedByDateFns.pt,
+  'zh-CN': supportedByDateFns.zhCN,
+  'zh-TW': supportedByDateFns.zhTW,
 };
 
 export function getForcedEnglishTimeLocale() {