Fix missing type support for i18n resources

Due to the change in 65a9a905be - moving to a json file - it wasn't ensured anymore that IsoLanguages contained the i18n language codes
This commit is contained in:
schroda
2026-01-30 21:46:20 +01:00
parent c5cdd347b7
commit edbbc81575
5 changed files with 47 additions and 37 deletions

View File

@@ -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',

View File

@@ -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();
}

View File

@@ -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}.<br/>
* 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',

View File

@@ -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"
}

View File

@@ -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"');
};