diff --git a/lingui.config.ts b/lingui.config.ts index 5ed5534f..233b4f19 100644 --- a/lingui.config.ts +++ b/lingui.config.ts @@ -13,7 +13,7 @@ import { formatter } from '@lingui/format-po'; // eslint-disable-next-line import/no-default-export export default defineConfig({ sourceLocale: 'en', - // This array is auto-generated by tools/scripts/weblate/generatei18nResources.ts. Do not edit manually. + // !!!IMPORTANT!!!: 'locales' is auto-generated by tools/scripts/weblate/generatei18nResources.ts. Do not edit manually. locales: [ 'de', 'en', diff --git a/src/features/metadata/Metadata.constants.ts b/src/features/metadata/Metadata.constants.ts index 2f38e771..97cab0b4 100644 --- a/src/features/metadata/Metadata.constants.ts +++ b/src/features/metadata/Metadata.constants.ts @@ -34,7 +34,7 @@ import { LibraryOptions } from '@/features/library/Library.types.ts'; import { MetadataThemeSettings } from '@/features/theme/AppTheme.types.ts'; import { TapZoneInvertMode } from '@/features/reader/tap-zones/TapZoneLayout.types.ts'; import { detectLocale, getISOLanguage } from '@/lib/ISOLanguageUtil.ts'; -import { i18nResources } from '@/i18n'; +import { I18nResourceCode, i18nResources } from '@/i18n'; import { toUniqueLanguageCodes } from '@/base/utils/Languages.ts'; export const APP_METADATA_KEY_PREFIX = 'webUI'; @@ -385,7 +385,7 @@ export const APP_METADATA: Record< toConstrainedValue: (value: string) => { const locale = getISOLanguage(value)?.isoCode; - if (!locale || !i18nResources.includes(locale)) { + if (!locale || !i18nResources.includes(locale as I18nResourceCode)) { return detectLocale(); } diff --git a/src/i18n/index.ts b/src/i18n/index.ts index 1fd9f3c6..6a9c46e0 100644 --- a/src/i18n/index.ts +++ b/src/i18n/index.ts @@ -10,7 +10,14 @@ import { i18n } from '@lingui/core'; import { detectLocale, SELECTED_LANGUAGE_CODE_KEY } from '@/lib/ISOLanguageUtil.ts'; import { AppStorage } from '@/lib/storage/AppStorage.ts'; -// This array is auto-generated by tools/scripts/weblate/generatei18nResources.ts. Do not edit manually. +/** + * Keys have to match {@link IsoLanguages} codes, they're used for showing the language name in the dropdown in the {@link Settings}.
+ * In case there is no language code for the key in {@link IsoLanguages}, the corresponding language has to be added + * + * **IMPORTANT:** + * + * This is generated by the `i18n:gen-resources` script + */ export const i18nResources = [ 'de', 'en', diff --git a/src/i18n/locales.json b/src/i18n/locales.json deleted file mode 100644 index fddb76f7..00000000 --- a/src/i18n/locales.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "comment": "!!!IMPORTANT!!!: 'locales' is auto generated by tools/scripts/weblate/generatei18nResources.ts. Do not edit manually.", - "locales": [ - "de", - "en", - "es", - "fa", - "fr", - "hu", - "it", - "ja", - "ko", - "pl", - "pt", - "ru", - "ta", - "tr", - "vi", - "zh_Hans", - "zh_Hant" - ], - "defaultLocale": "en" -} diff --git a/tools/scripts/weblate/generatei18nResources.ts b/tools/scripts/weblate/generatei18nResources.ts index ac0276d2..f560986e 100644 --- a/tools/scripts/weblate/generatei18nResources.ts +++ b/tools/scripts/weblate/generatei18nResources.ts @@ -17,9 +17,11 @@ import { import { WeblateLanguageStatistic } from './Weblate.types.ts'; import { TRANSLATED_PERCENT_THRESHOLD } from './Weblate.constants.ts'; -const FILE_PATH = 'src/i18n/locales.json'; +const I18N_INDEX_PATH = 'src/i18n/index.ts'; +const LINGUI_CONFIG_PATH = 'lingui.config.ts'; -const outputFilePath = path.join(import.meta.dirname, `../../../${FILE_PATH}`); +const i18nIndexFilePath = path.join(import.meta.dirname, `../../../${I18N_INDEX_PATH}`); +const linguiConfigFilePath = path.join(import.meta.dirname, `../../../${LINGUI_CONFIG_PATH}`); const resourcesDirPath = path.join(import.meta.dirname, '../../../src/i18n/locales'); const extractLanguageCode = (resourceFileNames: string): string => @@ -43,6 +45,25 @@ const meetsTranslatedPercentThreshold = ( return meetsThreshold; }; +const formatLocalesArray = (locales: string[]): string => locales.map((locale) => `'${locale}'`).join(', '); + +const updateI18nIndex = (locales: string[]): void => { + const content = fs.readFileSync(i18nIndexFilePath, 'utf-8'); + const localesArrayStr = formatLocalesArray(locales); + const updatedContent = content.replace( + /(export const i18nResources = \[)[\s\S]*?(] as const)/g, + `$1${localesArrayStr}$2`, + ); + fs.writeFileSync(i18nIndexFilePath, updatedContent); +}; + +const updateLinguiConfig = (locales: string[]): void => { + const content = fs.readFileSync(linguiConfigFilePath, 'utf-8'); + const localesArrayStr = formatLocalesArray(locales); + const updatedContent = content.replace(/(locales: \[)[\s\S]*?(],)/g, `$1${localesArrayStr}$2`); + fs.writeFileSync(linguiConfigFilePath, updatedContent); +}; + const generateResources = async () => { const weblateLanguageStats = await fetchWeblateLanguageStats(); @@ -52,21 +73,26 @@ const generateResources = async () => { .filter((resourceFileName) => meetsTranslatedPercentThreshold(resourceFileName, weblateLanguageStats)) .map(extractLanguageCode); - const localesConfig = JSON.parse(fs.readFileSync(outputFilePath, 'utf-8')); - - localesConfig.locales = resourceNames; - - fs.writeFileSync(outputFilePath, `${JSON.stringify(localesConfig, null, 2)}\n`); + updateI18nIndex(resourceNames); + updateLinguiConfig(resourceNames); execSync('yarn tsc', { stdio: 'inherit' }); + execSync(`yarn eslint --fix ${I18N_INDEX_PATH} ${LINGUI_CONFIG_PATH}`, { stdio: 'inherit' }); - const hasFileChanged = execSync('git status --porcelain').toString().includes(FILE_PATH); - if (!hasFileChanged) { + const hasI18nIndexChanged = execSync('git status --porcelain').toString().includes(I18N_INDEX_PATH); + const hasLinguiConfigChanged = execSync('git status --porcelain').toString().includes(LINGUI_CONFIG_PATH); + + if (!hasI18nIndexChanged && !hasLinguiConfigChanged) { return; } execSync('git reset'); - execSync(`git add ${FILE_PATH}`); + if (hasI18nIndexChanged) { + execSync(`git add ${I18N_INDEX_PATH}`); + } + if (hasLinguiConfigChanged) { + execSync(`git add ${LINGUI_CONFIG_PATH}`); + } execSync('git commit -m "Update available languages"'); };