···1+import {test, expect} from '@jest/globals'
2+3+import {sanitizeAppLanguageSetting} from '#/locale/helpers'
4+import {AppLanguage} from '#/locale/languages'
5+6+test('sanitizeAppLanguageSetting', () => {
7+ expect(sanitizeAppLanguageSetting('en')).toBe(AppLanguage.en)
8+ expect(sanitizeAppLanguageSetting('hi')).toBe(AppLanguage.hi)
9+ expect(sanitizeAppLanguageSetting('foo')).toBe(AppLanguage.en)
10+ expect(sanitizeAppLanguageSetting('en,fr')).toBe(AppLanguage.en)
11+ expect(sanitizeAppLanguageSetting('fr,en')).toBe(AppLanguage.en)
12+})
+28-5
src/locale/helpers.ts
···2import lande from 'lande'
3import {hasProp} from 'lib/type-guards'
4import * as bcp47Match from 'bcp-47-match'
5-import {LANGUAGES_MAP_CODE2, LANGUAGES_MAP_CODE3} from './languages'
000067export function code2ToCode3(lang: string): string {
8 if (lang.length === 2) {
···85 )}`
86}
8788-export function sanitizeAppLanguageSetting(appLanguage: string) {
0000000000000089 const langs = appLanguage.split(',').filter(Boolean)
9091 for (const lang of langs) {
92- if (['en', 'hi'].includes(lang)) {
93- return lang
0000094 }
95 }
9697- return 'en'
98}
···2import lande from 'lande'
3import {hasProp} from 'lib/type-guards'
4import * as bcp47Match from 'bcp-47-match'
5+import {
6+ AppLanguage,
7+ LANGUAGES_MAP_CODE2,
8+ LANGUAGES_MAP_CODE3,
9+} from './languages'
1011export function code2ToCode3(lang: string): string {
12 if (lang.length === 2) {
···89 )}`
90}
9192+/**
93+ * Returns a valid `appLanguage` value from an arbitrary string.
94+ *
95+ * Contenxt: post-refactor, we populated some user's `appLanguage` setting with
96+ * `postLanguage`, which can be a comma-separated list of values. This breaks
97+ * `appLanguage` handling in the app, so we introduced this util to parse out a
98+ * valid `appLanguage` from the pre-populated `postLanguage` values.
99+ *
100+ * The `appLanguage` will continue to be incorrect until the user returns to
101+ * language settings and selects a new option, at which point we'll re-save
102+ * their choice, which should then be a valid option. Since we don't know when
103+ * this will happen, we should leave this here until we feel it's safe to
104+ * remove, or we re-migrate their storage.
105+ */
106+export function sanitizeAppLanguageSetting(appLanguage: string): AppLanguage {
107 const langs = appLanguage.split(',').filter(Boolean)
108109 for (const lang of langs) {
110+ switch (lang) {
111+ case 'en':
112+ return AppLanguage.en
113+ case 'hi':
114+ return AppLanguage.hi
115+ default:
116+ continue
117 }
118 }
119120+ return AppLanguage.en
121}
+11-12
src/locale/i18n.ts
···5import {messages as messagesEn} from '#/locale/locales/en/messages'
6import {messages as messagesHi} from '#/locale/locales/hi/messages'
7import {sanitizeAppLanguageSetting} from '#/locale/helpers'
8-9-export const locales = {
10- en: 'English',
11- hi: 'हिंदी',
12-}
13-export const defaultLocale = 'en'
1415/**
16 * We do a dynamic import of just the catalog that we need
17- * @param locale any locale string
18 */
19-export async function dynamicActivate(locale: string) {
20- if (locale === 'hi') {
21- i18n.loadAndActivate({locale, messages: messagesHi})
22- } else {
23- i18n.loadAndActivate({locale, messages: messagesEn})
0000024 }
25}
26
···5import {messages as messagesEn} from '#/locale/locales/en/messages'
6import {messages as messagesHi} from '#/locale/locales/hi/messages'
7import {sanitizeAppLanguageSetting} from '#/locale/helpers'
8+import {AppLanguage} from '#/locale/languages'
00000910/**
11 * We do a dynamic import of just the catalog that we need
012 */
13+export async function dynamicActivate(locale: AppLanguage) {
14+ switch (locale) {
15+ case AppLanguage.hi: {
16+ i18n.loadAndActivate({locale, messages: messagesHi})
17+ break
18+ }
19+ default: {
20+ i18n.loadAndActivate({locale, messages: messagesEn})
21+ break
22+ }
23 }
24}
25
+11-12
src/locale/i18n.web.ts
···34import {useLanguagePrefs} from '#/state/preferences'
5import {sanitizeAppLanguageSetting} from '#/locale/helpers'
6-7-export const locales = {
8- en: 'English',
9- hi: 'हिंदी',
10-}
11-export const defaultLocale = 'en'
1213/**
14 * We do a dynamic import of just the catalog that we need
15- * @param locale any locale string
16 */
17-export async function dynamicActivate(locale: string) {
18 let mod: any
1920- if (locale === 'hi') {
21- mod = await import(`./locales/hi/messages`)
22- } else {
23- mod = await import(`./locales/en/messages`)
0000024 }
2526 i18n.load(locale, mod.messages)
···34import {useLanguagePrefs} from '#/state/preferences'
5import {sanitizeAppLanguageSetting} from '#/locale/helpers'
6+import {AppLanguage} from '#/locale/languages'
0000078/**
9 * We do a dynamic import of just the catalog that we need
010 */
11+export async function dynamicActivate(locale: AppLanguage) {
12 let mod: any
1314+ switch (locale) {
15+ case AppLanguage.hi: {
16+ mod = await import(`./locales/hi/messages`)
17+ break
18+ }
19+ default: {
20+ mod = await import(`./locales/en/messages`)
21+ break
22+ }
23 }
2425 i18n.load(locale, mod.messages)