From 2e53ac2ed22e667178bcbf2c935f9c599644aea9 Mon Sep 17 00:00:00 2001 From: LewisB Date: Thu, 14 Sep 2023 10:42:07 +0200 Subject: [PATCH] wip: dynamically load language locale maps --- package.json | 1 + scripts/i18n.js | 49 +++++++++++++++++++++++++++- src/components/dashboard/Settings.js | 46 +++----------------------- yarn.lock | 8 +++++ 4 files changed, 62 insertions(+), 42 deletions(-) diff --git a/package.json b/package.json index 4c739e15d5..aa501c87bb 100644 --- a/package.json +++ b/package.json @@ -349,6 +349,7 @@ "url-loader": "^4.1.1", "web-encoding": "^1.1.5", "webpack-manifest-plugin": "^2.2.0", + "windows-locale": "^1.1.3", "workbox-webpack-plugin": "^6.5.4" }, "dependenciesMeta": { diff --git a/scripts/i18n.js b/scripts/i18n.js index f53135ce00..4544ad9c89 100644 --- a/scripts/i18n.js +++ b/scripts/i18n.js @@ -9,6 +9,39 @@ const { writeFileSync } = require('fs') const package = require('../package.json') const { locales, sourceLocale } = package.lingui + +const lcid = require('windows-locale') + +// setup locale map for language selector + +// some locales are not directly mappable to a country code and then would fail to retreive a flag icon +const customLocaleMap = [ + { code: 'en', countryCode: 'US', name: 'English-United States' }, + { code: 'es-419', countryCode: 'AR', name: 'Español Latinoamericano' }, + { code: 'hi', countryCode: 'IN', name: 'हिन्दी' }, + { code: 'zh', countryCode: 'CN', name: '中文' }, + { code: 'uk', countryCode: 'UA', name: 'Українська' }, + { code: 'ko', countryCode: 'KR', name: '한국어' }, + { code: 'vi', countryCode: 'VN', name: 'Tiếng Việt' }, + { code: 'es-us', countryCode: 'UM', name: 'Español-United States' }, +] + +// filter custom locales out of the locales array +const filteredLocales = locales.filter(locale => !customLocaleMap.map(customLocale => customLocale.code).includes(locale)); + +// map the filtered locales to a country code (used for retreiving flag icons) +// and their language name (used in language selector) +const localeCodeMap = filteredLocales.map(locale => { + const { language, location } = lcid[locale] + const countryCode = locale.split('-').at(-1).toUpperCase() + + // todo: get native translation of language name + const name = language + (location ? '-' + location : '') + + return customLocaleMap.push({ code: locale, countryCode: countryCode, name: name }) +}) + +// Prepare build + json files const localeCode = locale => `'${locale}'` const localeKey = locale => locale.includes('-') ? localeCode(locale) : locale const localeFilesPath = join(__dirname, '../src/language/locales', 'index.js') @@ -24,11 +57,25 @@ export const sourceLocale = <%= localeCode(sourceLocale) %> export const localeFiles = {<% _.forEach(locales, function(locale) { %> <%= localeKey(locale) %>: () => import('./<%= locale %>/catalog.js'),<% }) %> } + +// for supported country list in language selector +export const countryCodes = [<% _.forEach(customLocaleMap, function(locale) { %> + '<%= locale.countryCode %>',<% }) %> +] + +export const countryCodeToLocale = {<% _.forEach(customLocaleMap, function(locale) { %> + <%= localeCode(locale.countryCode) %>: '<%= locale.code %>',<% }) %> +} + +export const languageLabels = {<% _.forEach(customLocaleMap, function(locale) { %> + <%= localeCode(locale.countryCode) %>: '<%= locale.name %>',<% }) %> +} `) writeFileSync(localeFilesPath, localeFilesTmpl({ sourceLocale, locales, localeKey, - localeCode + localeCode, + customLocaleMap })) diff --git a/src/components/dashboard/Settings.js b/src/components/dashboard/Settings.js index 0e0257538b..4676d0518d 100644 --- a/src/components/dashboard/Settings.js +++ b/src/components/dashboard/Settings.js @@ -17,6 +17,7 @@ import { useDebounce } from 'use-debounce' import Wrapper from '../common/layout/Wrapper' import { Icon, Section, Text } from '../common' import { LanguageContext } from '../../language/i18n' +import { countryCodes, countryCodeToLocale, languageLabels } from '../../language/locales' import { CountryFlag } from '../profile/ProfileDataTable' // hooks @@ -66,43 +67,6 @@ const PrivacyOption = ({ title, value, field, setPrivacy }) => { ) } -const supportedCountryCodes = ['US', 'GB', 'ES', 'FR', 'IT', 'KR', 'BR', 'UA', 'TR', 'VN', 'CN', 'IN', 'ID', 'AR'] -type CountryCode = $ElementType - -const countryCodeToLocale: { [key: CountryCode]: string } = { - US: 'en', - GB: 'en-gb', - ES: 'es', - FR: 'fr', - IT: 'it', - KR: 'ko', - BR: 'pt-br', - UA: 'uk', - TR: 'tr', - VN: 'vi', - CN: 'zh', - IN: 'hi', - ID: 'id', - AR: 'es-419', -} - -const languageCustomLabels: { [key: CountryCode]: string } = { - US: 'English-US', - GB: 'English-UK', - ES: 'Spanish', - FR: 'French', - IT: 'Italian', - KR: 'Korean', - DE: 'German', - BR: 'Portuguese-Brazilian', - UA: 'Ukrainian', - TR: 'Turkish', - VN: 'Vietnamese', - CN: 'Chinese-Simplified', - IN: 'Hindi', - ID: 'Indonesian', - AR: 'Latin-Spanish', -} const getKeyByValue = (object, value) => { return Object.keys(object).find(key => object[key] === value) @@ -111,7 +75,7 @@ const getKeyByValue = (object, value) => { const DropDownRowComponent = props => { const { containerStyles, textStyles, children } = props const { children: countryCode } = children.props - const countryLabel = languageCustomLabels[countryCode] ?? 'Device Default' + const countryLabel = languageLabels[countryCode] ?? 'Device Default' return ( @@ -291,13 +255,13 @@ const Settings = ({ screenProps, styles, theme, navigation }) => { { - const language = languageCustomLabels[option] ?? 'Device Default' + const language = languageLabels[option] ?? 'Device Default' return t`${language}` }} renderRowComponent={DropDownRowComponent} diff --git a/yarn.lock b/yarn.lock index bcfb7a7876..a0201f7cba 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4403,6 +4403,7 @@ __metadata: webpack-bundle-analyzer: ^4.5.0 webpack-manifest-plugin: ^2.2.0 websocket: ^1.0.31 + windows-locale: ^1.1.3 workbox-webpack-plugin: ^6.5.4 languageName: unknown linkType: soft @@ -41364,6 +41365,13 @@ __metadata: languageName: node linkType: hard +"windows-locale@npm:^1.1.3": + version: 1.1.3 + resolution: "windows-locale@npm:1.1.3" + checksum: c3c4a3887212d94442bf3d3c205b54ade1fbbf352ba83f7d32de6cceea8f14d3605ce16b88d9f4735448c0d9e1c7dd2db2afcaa04bc0da545a265aca832f1d57 + languageName: node + linkType: hard + "winston@npm:2.x": version: 2.4.7 resolution: "winston@npm:2.4.7"