Fix "auto webtoon mode" detection

The detection didn't work properly in case the selected manga was in a different language than English or the current active translation.
In that case it didn't work because the translation for that locale wasn't loaded.

So to ensure that the translation exists for each language, we have to hardcode it.
This commit is contained in:
schroda
2026-02-21 21:22:54 +01:00
parent 576cf85c38
commit 41fe42f29b
7 changed files with 223 additions and 28 deletions

View File

@@ -152,10 +152,124 @@ export const SOURCES_BY_MANGA_TYPE: Record<MangaType, string[]> = {
],
};
export const MANGA_TAGS_BY_MANGA_TYPE: Record<MangaType, MessageDescriptor[]> = {
/**
* Lingui extraction markers — DO NOT remove.
* These `msg` calls ensure the strings stay in .po files for translation.
* The actual matching data is in {@link MANGA_TAGS_BY_MANGA_TYPE} below.
*/
// @ts-ignore - see comment
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const MANGA_TAG_DESCRIPTORS_BY_MANGA_TYPE: Record<MangaType, MessageDescriptor[]> = {
[MangaType.MANGA]: [msg`Manga`],
[MangaType.COMIC]: [msg`Comic`],
[MangaType.WEBTOON]: [msg`Webtoon`, msg`Long strip`],
[MangaType.MANHWA]: [msg`Manhwa`, msg`Long strip`],
[MangaType.MANHUA]: [msg`Manhua`, msg`Long strip`],
};
/**
* All translations of manga type tags across all available locales.
* Used for matching manga genres to detect manga type regardless of source language.
*
* **IMPORTANT:**
*
* This is generated by the `manga:gen-type-tags` script
*/
export const MANGA_TAGS_BY_MANGA_TYPE: Record<MangaType, string[]> = {
[MangaType.MANGA]: ['Manga', 'مانگا', 'Mangá', 'Манга', 'மங்கா-', 'Truyện Nhật'],
[MangaType.COMIC]: [
'Comic',
'کمیک',
'Komik',
'Fumetti',
'アメコミ',
'만화',
'Komiks',
'Quadrinhos',
'Комикс',
'காமிக்',
'Çizgi roman',
'Truyện Hoa Kỳ',
'美漫',
],
[MangaType.WEBTOON]: [
'Webtoon',
'Long strip',
'ويبتون',
'وبتون',
'ウェブトゥーン',
'웹툰',
'Веб-комикс',
'வெப்டூன்-',
'Вебтун',
'条漫',
'條漫',
'Tira larga',
'نوار بلند',
'Bande continue',
'Függőleges folyamatos',
'Strip panjang',
'Striscia lunga',
'縦読み漫画',
'긴 스트립',
'Długi pasek',
'Tira longa',
'Длинная полоска',
'நீண்ட துண்டு',
'Uzun şerit',
],
[MangaType.MANHWA]: [
'Manhwa',
'Long strip',
'مانهوا',
'韓国マンガ',
'만화',
'Манхва',
'மன்அ்வா',
'Truyện Hàn',
'韩漫',
'韓漫',
'Tira larga',
'نوار بلند',
'Bande continue',
'Függőleges folyamatos',
'Strip panjang',
'Striscia lunga',
'긴 스트립',
'Długi pasek',
'Tira longa',
'Длинная полоска',
'நீண்ட துண்டு',
'Uzun şerit',
'Cuộn dọc',
'条漫',
'條漫',
],
[MangaType.MANHUA]: [
'Manhua',
'Long strip',
'مانها',
'漫画',
'만화',
'Маньхуа',
'மன்உவா',
'Truyện Trung',
'國漫',
'Tira larga',
'نوار بلند',
'Bande continue',
'Függőleges folyamatos',
'Strip panjang',
'Striscia lunga',
'縦読み漫画',
'긴 스트립',
'Długi pasek',
'Tira longa',
'Длинная полоска',
'நீண்ட துண்டு',
'Uzun şerit',
'Cuộn dọc',
'条漫',
'條漫',
],
};

View File

@@ -35,7 +35,6 @@ import {
MangaGenreInfo,
MangaIdInfo,
MangaLocationState,
MangaSourceLngInfo,
MangaSourceNameInfo,
MangaThumbnailInfo,
MangaTitleInfo,
@@ -53,7 +52,6 @@ import { getErrorMessage } from '@/lib/HelperFunctions.ts';
import { assertIsDefined } from '@/base/Asserts.ts';
import { Confirmation } from '@/base/AppAwaitableComponent.ts';
import { UrlUtil } from '@/lib/UrlUtil.ts';
import { DEFAULT_LANGUAGE } from '@/lib/ISOLanguageUtil.ts';
type MangaToMigrate = NonNullable<GetMangaToMigrateQuery['manga']>;
type MangaToMigrateTo = NonNullable<GetMangaToMigrateToFetchMutation['fetchManga']>['manga'];
@@ -630,7 +628,7 @@ export class Mangas {
}
}
static getType(manga: MangaGenreInfo & MangaSourceNameInfo & MangaSourceLngInfo): MangaType {
static getType(manga: MangaGenreInfo & MangaSourceNameInfo): MangaType {
if (Mangas.isType(manga, MangaType.MANGA)) {
return MangaType.MANGA;
}
@@ -654,35 +652,16 @@ export class Mangas {
return MangaType.MANGA;
}
static isType(manga: MangaGenreInfo & MangaSourceNameInfo & MangaSourceLngInfo, type: MangaType): boolean {
const translateMangaTagsByMangaTypeEntries = Object.entries(MANGA_TAGS_BY_MANGA_TYPE).map(
([mangaType, tags]) => [
mangaType,
[DEFAULT_LANGUAGE, i18n.locale, manga.source?.lang]
.filter((lng) => !!lng)
.flatMap((language) =>
tags.flatMap((tag) =>
/* lingui-extract-ignore */
i18n.t({ ...tag, values: { lng: language } }),
),
),
],
);
const translatedMangaTagsByMangaType = Object.fromEntries(translateMangaTagsByMangaTypeEntries) as Record<
string,
string[]
>;
static isType(manga: MangaGenreInfo & MangaSourceNameInfo, type: MangaType): boolean {
const isMatchByGenre = manga.genre.some((genre) =>
translatedMangaTagsByMangaType[type].some((tag) => genre.toLowerCase().includes(tag.toLowerCase())),
MANGA_TAGS_BY_MANGA_TYPE[type].some((tag) => genre.toLowerCase().includes(tag.toLowerCase())),
);
const isMatchBySource = SOURCES_BY_MANGA_TYPE[type].includes(manga.source?.name.toLowerCase() ?? '');
return isMatchByGenre || isMatchBySource;
}
static isLongStripType(manga: MangaGenreInfo & MangaSourceNameInfo & MangaSourceLngInfo): boolean {
static isLongStripType(manga: MangaGenreInfo & MangaSourceNameInfo): boolean {
return (
Mangas.isType(manga, MangaType.WEBTOON) ||
Mangas.isType(manga, MangaType.MANHWA) ||

View File

@@ -16,7 +16,7 @@ import {
ReaderPageScaleMode,
ReadingMode,
} from '@/features/reader/Reader.types.ts';
import { MangaGenreInfo, MangaSourceLngInfo, MangaSourceNameInfo } from '@/features/manga/Manga.types.ts';
import { MangaGenreInfo, MangaSourceNameInfo } from '@/features/manga/Manga.types.ts';
import { Mangas } from '@/features/manga/services/Mangas.ts';
import { ReaderPagedPager } from '@/features/reader/viewer/pager/components/ReaderPagedPager.tsx';
import { ReaderDoublePagedPager } from '@/features/reader/viewer/pager/components/ReaderDoublePagedPager.tsx';
@@ -57,7 +57,7 @@ export const isContinuousVerticalReadingMode = (readingMode: IReaderSettings['re
[ReadingMode.CONTINUOUS_VERTICAL, ReadingMode.WEBTOON].includes(readingMode);
export const isAutoWebtoonMode = (
manga: MangaGenreInfo & MangaSourceNameInfo & MangaSourceLngInfo,
manga: MangaGenreInfo & MangaSourceNameInfo,
shouldUseAutoWebtoonMode: IReaderSettings['shouldUseAutoWebtoonMode'],
readingMode: IReaderSettingsWithDefaultFlag['readingMode'],
): boolean => shouldUseAutoWebtoonMode && readingMode.isDefault && Mangas.isLongStripType(manga);