compat(epub): detect missing writing direction for some EPUBs (#2803)
This commit is contained in:
@@ -132,7 +132,8 @@ const FoliateViewer: React.FC<{
|
||||
const bookData = getBookData(bookKey);
|
||||
if (viewSettings && detail.type === 'text/css')
|
||||
return transformStylesheet(data, width, height, viewSettings.vertical);
|
||||
if (viewSettings && bookData && detail.type === 'application/xhtml+xml') {
|
||||
const isHtml = detail.type === 'application/xhtml+xml' || detail.type === 'text/html';
|
||||
if (viewSettings && bookData && isHtml) {
|
||||
const ctx: TransformContext = {
|
||||
bookKey,
|
||||
viewSettings,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { detectLanguage, isSameLang, isValidLang } from '@/utils/lang';
|
||||
import { detectLanguage, getLanguageInfo, isSameLang, isValidLang } from '@/utils/lang';
|
||||
import type { Transformer } from './types';
|
||||
|
||||
export const languageTransformer: Transformer = {
|
||||
@@ -21,12 +21,25 @@ export const languageTransformer: Transformer = {
|
||||
isValidLang(primaryLanguage) && primaryLanguage !== 'en'
|
||||
? primaryLanguage
|
||||
: detectLanguage(mainContent);
|
||||
const languageInfo = getLanguageInfo(lang || '');
|
||||
const newLangAttr = ` lang="${lang}"`;
|
||||
const newXmlLangAttr = ` xml:lang="${lang}"`;
|
||||
attrs = langMatch ? attrs.replace(langRegex, newLangAttr) : attrs + newLangAttr;
|
||||
attrs = xmlLangMatch ? attrs.replace(xmlLangRegex, newXmlLangAttr) : attrs + newXmlLangAttr;
|
||||
const dirAttr = languageInfo?.direction === 'rtl' ? ' dir="rtl"' : '';
|
||||
attrs = langMatch ? attrs.replace(langRegex, newLangAttr) : attrs + newLangAttr + dirAttr;
|
||||
attrs = xmlLangMatch
|
||||
? attrs.replace(xmlLangRegex, newXmlLangAttr)
|
||||
: attrs + newXmlLangAttr + dirAttr;
|
||||
result = result.replace(attrsMatch[0], `<html${attrs}>`);
|
||||
}
|
||||
} else {
|
||||
const lang =
|
||||
isValidLang(primaryLanguage) && primaryLanguage !== 'en'
|
||||
? primaryLanguage
|
||||
: detectLanguage(result.replace(/<[^>]+>/g, ' '));
|
||||
const languageInfo = getLanguageInfo(lang || '');
|
||||
const dirAttr = languageInfo?.direction === 'rtl' ? ' dir="rtl"' : '';
|
||||
const newAttrs = ` lang="${lang}" xml:lang="${lang}" ${dirAttr}`;
|
||||
result = result.replace(/<html>/i, `<html${newAttrs}>`);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
@@ -4,3 +4,8 @@ export type Insets = {
|
||||
left: number;
|
||||
right: number;
|
||||
};
|
||||
|
||||
export interface LocaleWithTextInfo extends Intl.Locale {
|
||||
getTextInfo?: () => { direction: string };
|
||||
textInfo?: { direction: string };
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { BookDoc } from '@/libs/document';
|
||||
import { BookNote, BookSearchConfig, BookSearchResult } from '@/types/book';
|
||||
import { TTSGranularity } from '@/services/tts';
|
||||
import { TTS } from 'foliate-js/tts.js';
|
||||
import { LocaleWithTextInfo } from './misc';
|
||||
|
||||
export const NOTE_PREFIX = 'foliate-note:';
|
||||
|
||||
@@ -33,8 +34,10 @@ export interface FoliateView extends HTMLElement {
|
||||
book: BookDoc;
|
||||
tts: TTS | null;
|
||||
language: {
|
||||
locale?: string;
|
||||
locale?: LocaleWithTextInfo;
|
||||
isCJK?: boolean;
|
||||
canonical?: string;
|
||||
direction?: string;
|
||||
};
|
||||
history: {
|
||||
canGoBack: boolean;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { LocaleWithTextInfo } from '@/types/misc';
|
||||
import { franc } from 'franc-min';
|
||||
import { iso6392 } from 'iso-639-2';
|
||||
import { iso6393To1 } from 'iso-639-3';
|
||||
@@ -116,3 +117,17 @@ export const detectLanguage = (content: string): string => {
|
||||
return 'en';
|
||||
}
|
||||
};
|
||||
|
||||
export const getLanguageInfo = (lang: string) => {
|
||||
if (!lang) return {};
|
||||
try {
|
||||
const canonical = Intl.getCanonicalLocales(lang)[0]!;
|
||||
const locale = new Intl.Locale(canonical) as LocaleWithTextInfo;
|
||||
const isCJK = ['zh', 'ja', 'kr'].includes(locale.language);
|
||||
const direction = (locale.getTextInfo?.() ?? locale.textInfo)?.direction;
|
||||
return { canonical, locale, isCJK, direction };
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user