forked from akai/readest
This commit is contained in:
@@ -271,5 +271,6 @@
|
||||
"{{value}} minute": "{{value}} دقيقة",
|
||||
"{{value}} minutes": "{{value}} دقائق",
|
||||
"{{value}} hour": "{{value}} ساعة",
|
||||
"{{value}} hours": "{{value}} ساعات"
|
||||
"{{value}} hours": "{{value}} ساعات",
|
||||
"CJK Font": "خط CJK"
|
||||
}
|
||||
|
||||
@@ -271,5 +271,6 @@
|
||||
"{{value}} minute": "{{value}} Minute",
|
||||
"{{value}} minutes": "{{value}} Minuten",
|
||||
"{{value}} hour": "{{value}} Stunde",
|
||||
"{{value}} hours": "{{value}} Stunden"
|
||||
"{{value}} hours": "{{value}} Stunden",
|
||||
"CJK Font": "CJK-Schriftart"
|
||||
}
|
||||
|
||||
@@ -271,5 +271,6 @@
|
||||
"{{value}} minute": "{{value}} λεπτό",
|
||||
"{{value}} minutes": "{{value}} λεπτά",
|
||||
"{{value}} hour": "{{value}} ώρα",
|
||||
"{{value}} hours": "{{value}} ώρες"
|
||||
"{{value}} hours": "{{value}} ώρες",
|
||||
"CJK Font": "Γραμματοσειρά CJK"
|
||||
}
|
||||
|
||||
@@ -271,5 +271,6 @@
|
||||
"{{value}} minute": "{{value}} minuto",
|
||||
"{{value}} minutes": "{{value}} minutos",
|
||||
"{{value}} hour": "{{value}} hora",
|
||||
"{{value}} hours": "{{value}} horas"
|
||||
"{{value}} hours": "{{value}} horas",
|
||||
"CJK Font": "Fuente CJK"
|
||||
}
|
||||
|
||||
@@ -271,5 +271,6 @@
|
||||
"{{value}} minute": "{{value}} minute",
|
||||
"{{value}} minutes": "{{value}} minutes",
|
||||
"{{value}} hour": "{{value}} heure",
|
||||
"{{value}} hours": "{{value}} heures"
|
||||
"{{value}} hours": "{{value}} heures",
|
||||
"CJK Font": "Police CJK"
|
||||
}
|
||||
|
||||
@@ -271,5 +271,6 @@
|
||||
"{{value}} minute": "{{value}} मिनट",
|
||||
"{{value}} minutes": "{{value}} मिनट",
|
||||
"{{value}} hour": "{{value}} घंटा",
|
||||
"{{value}} hours": "{{value}} घंटे"
|
||||
"{{value}} hours": "{{value}} घंटे",
|
||||
"CJK Font": "CJK फ़ॉन्ट"
|
||||
}
|
||||
|
||||
@@ -271,5 +271,6 @@
|
||||
"{{value}} minute": "{{value}} menit",
|
||||
"{{value}} minutes": "{{value}} menit",
|
||||
"{{value}} hour": "{{value}} jam",
|
||||
"{{value}} hours": "{{value}} jam"
|
||||
"{{value}} hours": "{{value}} jam",
|
||||
"CJK Font": "Font CJK"
|
||||
}
|
||||
|
||||
@@ -271,5 +271,6 @@
|
||||
"{{value}} minute": "{{value}} minuto",
|
||||
"{{value}} minutes": "{{value}} minuti",
|
||||
"{{value}} hour": "{{value}} ora",
|
||||
"{{value}} hours": "{{value}} ore"
|
||||
"{{value}} hours": "{{value}} ore",
|
||||
"CJK Font": "Font CJK"
|
||||
}
|
||||
|
||||
@@ -271,5 +271,6 @@
|
||||
"{{value}} minute": "{{value}}分",
|
||||
"{{value}} minutes": "{{value}}分",
|
||||
"{{value}} hour": "{{value}}時間",
|
||||
"{{value}} hours": "{{value}}時間"
|
||||
"{{value}} hours": "{{value}}時間",
|
||||
"CJK Font": "CJKフォント"
|
||||
}
|
||||
|
||||
@@ -271,5 +271,6 @@
|
||||
"{{value}} minute": "{{value}} 분",
|
||||
"{{value}} minutes": "{{value}} 분",
|
||||
"{{value}} hour": "{{value}} 시간",
|
||||
"{{value}} hours": "{{value}} 시간"
|
||||
"{{value}} hours": "{{value}} 시간",
|
||||
"CJK Font": "CJK 글꼴"
|
||||
}
|
||||
|
||||
@@ -271,5 +271,6 @@
|
||||
"{{value}} minute": "{{value}} minuta",
|
||||
"{{value}} minutes": "{{value}} minut",
|
||||
"{{value}} hour": "{{value}} godzina",
|
||||
"{{value}} hours": "{{value}} godziny"
|
||||
"{{value}} hours": "{{value}} godziny",
|
||||
"CJK Font": "Czcionka CJK"
|
||||
}
|
||||
|
||||
@@ -271,5 +271,6 @@
|
||||
"{{value}} minute": "{{value}} minuto",
|
||||
"{{value}} minutes": "{{value}} minutos",
|
||||
"{{value}} hour": "{{value}} hora",
|
||||
"{{value}} hours": "{{value}} horas"
|
||||
"{{value}} hours": "{{value}} horas",
|
||||
"CJK Font": "Fonte CJK"
|
||||
}
|
||||
|
||||
@@ -271,5 +271,6 @@
|
||||
"{{value}} minute": "{{value}} минута",
|
||||
"{{value}} minutes": "{{value}} минуты",
|
||||
"{{value}} hour": "{{value}} час",
|
||||
"{{value}} hours": "{{value}} часа"
|
||||
"{{value}} hours": "{{value}} часа",
|
||||
"CJK Font": "CJK Шрифт"
|
||||
}
|
||||
|
||||
@@ -271,5 +271,6 @@
|
||||
"{{value}} minute": "{{value}} dakika",
|
||||
"{{value}} minutes": "{{value}} dakika",
|
||||
"{{value}} hour": "{{value}} saat",
|
||||
"{{value}} hours": "{{value}} saat"
|
||||
"{{value}} hours": "{{value}} saat",
|
||||
"CJK Font": "CJK Yazı Tipi"
|
||||
}
|
||||
|
||||
@@ -271,5 +271,6 @@
|
||||
"{{value}} minute": "{{value}} хвилина",
|
||||
"{{value}} minutes": "{{value}} хвилин",
|
||||
"{{value}} hour": "{{value}} година",
|
||||
"{{value}} hours": "{{value}} години"
|
||||
"{{value}} hours": "{{value}} години",
|
||||
"CJK Font": "CJK шрифт"
|
||||
}
|
||||
|
||||
@@ -271,5 +271,6 @@
|
||||
"{{value}} minute": "{{value}} phút",
|
||||
"{{value}} minutes": "{{value}} phút",
|
||||
"{{value}} hour": "{{value}} giờ",
|
||||
"{{value}} hours": "{{value}} giờ"
|
||||
"{{value}} hours": "{{value}} giờ",
|
||||
"CJK Font": "Phông chữ CJK"
|
||||
}
|
||||
|
||||
@@ -271,5 +271,6 @@
|
||||
"{{value}} minute": "{{value}}分钟",
|
||||
"{{value}} minutes": "{{value}}分钟",
|
||||
"{{value}} hour": "{{value}}小时",
|
||||
"{{value}} hours": "{{value}}小时"
|
||||
"{{value}} hours": "{{value}}小时",
|
||||
"CJK Font": "中文字体"
|
||||
}
|
||||
|
||||
@@ -271,5 +271,6 @@
|
||||
"{{value}} minute": "{{value}}分鐘",
|
||||
"{{value}} minutes": "{{value}}分鐘",
|
||||
"{{value}} hour": "{{value}}小時",
|
||||
"{{value}} hours": "{{value}}小時"
|
||||
"{{value}} hours": "{{value}}小時",
|
||||
"CJK Font": "中文字體"
|
||||
}
|
||||
|
||||
@@ -41,7 +41,10 @@ const FontDropdown: React.FC<DropdownProps> = ({
|
||||
</button>
|
||||
<ul
|
||||
tabIndex={0}
|
||||
className='dropdown-content bgcolor-base-200 no-triangle menu rounded-box absolute right-[-32px] z-[1] mt-4 w-44 shadow sm:right-0'
|
||||
className={clsx(
|
||||
'dropdown-content bgcolor-base-200 no-triangle menu rounded-box absolute right-[-32px] z-[1] mt-4 w-44 shadow sm:right-0',
|
||||
'inline max-h-80 overflow-y-scroll',
|
||||
)}
|
||||
>
|
||||
{options.map(({ option, label }) => (
|
||||
<li key={option} onClick={() => onSelect(option)}>
|
||||
|
||||
@@ -3,6 +3,8 @@ import React, { useEffect, useState } from 'react';
|
||||
|
||||
import {
|
||||
ANDROID_FONTS,
|
||||
CJK_FONTS_PATTENS,
|
||||
CJK_NAMES_PATTENS,
|
||||
IOS_FONTS,
|
||||
LINUX_FONTS,
|
||||
MACOS_FONTS,
|
||||
@@ -14,7 +16,7 @@ import {
|
||||
import { useReaderStore } from '@/store/readerStore';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { useEnv } from '@/context/EnvContext';
|
||||
import { getOSPlatform } from '@/utils/misc';
|
||||
import { getOSPlatform, isCJKEnv } from '@/utils/misc';
|
||||
import { getSysFontsList } from '@/utils/font';
|
||||
import { isTauriAppPlatform } from '@/services/environment';
|
||||
import { saveViewSettings } from '../../utils/viewSettingsHelper';
|
||||
@@ -63,8 +65,9 @@ const FontFace = ({
|
||||
const FontPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
const _ = useTranslation();
|
||||
const { envConfig, appService } = useEnv();
|
||||
const { getViewSettings } = useReaderStore();
|
||||
const { getView, getViewSettings } = useReaderStore();
|
||||
const viewSettings = getViewSettings(bookKey)!;
|
||||
const view = getView(bookKey)!;
|
||||
|
||||
const fontFamilyOptions = [
|
||||
{
|
||||
@@ -103,6 +106,7 @@ const FontPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
const [minFontSize, setMinFontSize] = useState(viewSettings.minimumFontSize!);
|
||||
const [overrideFont, setOverrideFont] = useState(viewSettings.overrideFont!);
|
||||
const [defaultFont, setDefaultFont] = useState(viewSettings.defaultFont!);
|
||||
const [defaultCJKFont, setDefaultCJKFont] = useState(viewSettings.defaultCJKFont!);
|
||||
const [serifFont, setSerifFont] = useState(viewSettings.serifFont!);
|
||||
const [sansSerifFont, setSansSerifFont] = useState(viewSettings.sansSerifFont!);
|
||||
const [monospaceFont, setMonospaceFont] = useState(viewSettings.monospaceFont!);
|
||||
@@ -122,6 +126,11 @@ const FontPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [defaultFont]);
|
||||
|
||||
useEffect(() => {
|
||||
saveViewSettings(envConfig, bookKey, 'defaultCJKFont', defaultCJKFont);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [defaultCJKFont]);
|
||||
|
||||
useEffect(() => {
|
||||
saveViewSettings(envConfig, bookKey, 'defaultFontSize', defaultFontSize);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
@@ -224,6 +233,19 @@ const FontPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
/>
|
||||
</div>
|
||||
|
||||
{(isCJKEnv() || view?.language.isCJK) && (
|
||||
<FontFace
|
||||
className='config-item-top'
|
||||
family='serif'
|
||||
label={_('CJK Font')}
|
||||
options={sysFonts.filter(
|
||||
(font) => CJK_FONTS_PATTENS.test(font) || CJK_NAMES_PATTENS.test(font),
|
||||
)}
|
||||
selected={defaultCJKFont}
|
||||
onSelect={setDefaultCJKFont}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className='config-item'>
|
||||
<span className=''>{_('Override Book Font')}</span>
|
||||
<input
|
||||
|
||||
@@ -66,6 +66,7 @@ export const DEFAULT_BOOK_FONT: BookFont = {
|
||||
sansSerifFont: 'Roboto',
|
||||
monospaceFont: 'Consolas',
|
||||
defaultFont: 'Serif',
|
||||
defaultCJKFont: 'LXGW WenKai GB Screen',
|
||||
defaultFontSize: 16,
|
||||
minimumFontSize: 8,
|
||||
fontWeight: 400,
|
||||
@@ -181,6 +182,7 @@ export const WINDOWS_FONTS = [
|
||||
'Leelawadee UI',
|
||||
'Lucida Console',
|
||||
'Lucida Sans Unicode',
|
||||
'LXGW WenKai GB Screen',
|
||||
'Malgun Gothic',
|
||||
'Marlett',
|
||||
'Microsoft Himalaya',
|
||||
@@ -275,6 +277,7 @@ export const MACOS_FONTS = [
|
||||
'Kozuka Mincho Pro',
|
||||
'Lucida Grande',
|
||||
'Luminari',
|
||||
'LXGW WenKai GB Screen',
|
||||
'Marker Felt',
|
||||
'Menlo',
|
||||
'Microsoft Sans Serif',
|
||||
@@ -331,6 +334,7 @@ export const LINUX_FONTS = [
|
||||
'Liberation Mono',
|
||||
'Liberation Sans',
|
||||
'Liberation Serif',
|
||||
'LXGW WenKai GB Screen',
|
||||
'Noto Mono',
|
||||
'Noto Sans',
|
||||
'Noto Sans JP',
|
||||
@@ -367,6 +371,7 @@ export const IOS_FONTS = [
|
||||
'Hiragino Mincho',
|
||||
'Hiragino Sans',
|
||||
'Kaiti',
|
||||
'LXGW WenKai GB Screen',
|
||||
'Palatino',
|
||||
'PingFang SC',
|
||||
'PingFang TC',
|
||||
@@ -389,6 +394,7 @@ export const ANDROID_FONTS = [
|
||||
'Georgia',
|
||||
'Heiti',
|
||||
'Kaiti',
|
||||
'LXGW WenKai GB Screen',
|
||||
'Noto Sans',
|
||||
'Noto Sans CJK',
|
||||
'Noto Sans JP',
|
||||
@@ -406,6 +412,47 @@ export const ANDROID_FONTS = [
|
||||
'XiHeiti',
|
||||
];
|
||||
|
||||
export const CJK_NAMES_PATTENS = /[\u3040-\u30FF\u4E00-\u9FFF\uAC00-\uD7AF]/;
|
||||
export const CJK_FONTS_PATTENS = new RegExp(
|
||||
[
|
||||
'CJK',
|
||||
'TC$',
|
||||
'SC$',
|
||||
'HK',
|
||||
'JP',
|
||||
'TW',
|
||||
'Sim',
|
||||
'Kai',
|
||||
'Hei',
|
||||
'Yan',
|
||||
'Min',
|
||||
'Yuan',
|
||||
'Song',
|
||||
'Ming',
|
||||
'FZ',
|
||||
'FangZheng',
|
||||
'WenQuanYi',
|
||||
'PingFang',
|
||||
'Hiragino',
|
||||
'Meiryo',
|
||||
'Source\\s?Han',
|
||||
'Yu\\s?Gothic',
|
||||
'Yu\\s?Mincho',
|
||||
'Mincho',
|
||||
'Gothic',
|
||||
'Nanum',
|
||||
'Malgun',
|
||||
'Gulim',
|
||||
'Dotum',
|
||||
'Batang',
|
||||
'Gungsuh',
|
||||
'OPPO sans',
|
||||
'MiSans',
|
||||
'Fallback',
|
||||
].join('|'),
|
||||
'i',
|
||||
);
|
||||
|
||||
export const BOOK_IDS_SEPARATOR = '+';
|
||||
|
||||
export const DOWNLOAD_READEST_URL = 'https://readest.com?utm_source=readest_web';
|
||||
|
||||
@@ -105,6 +105,7 @@ export interface BookFont {
|
||||
sansSerifFont: string;
|
||||
monospaceFont: string;
|
||||
defaultFont: string;
|
||||
defaultCJKFont: string;
|
||||
defaultFontSize: number;
|
||||
minimumFontSize: number;
|
||||
fontWeight: number;
|
||||
|
||||
@@ -32,7 +32,12 @@ export const makeSafeFilename = (filename: string, replacement = '_') => {
|
||||
|
||||
export const getUserLang = () => navigator?.language.split('-')[0] || 'en';
|
||||
|
||||
export const isCJKEnv = () => ['zh', 'ja', 'ko'].includes(getUserLang());
|
||||
export const isCJKEnv = () => {
|
||||
const isCJKLocale = ['zh', 'ja', 'ko'].includes(getUserLang());
|
||||
const uiLanguage = localStorage.getItem('i18nextLng') || '';
|
||||
const isCJKUI = ['zh', 'ja', 'ko'].some((lang) => uiLanguage.startsWith(lang));
|
||||
return isCJKLocale || isCJKUI;
|
||||
};
|
||||
|
||||
export const getUserLocale = (lang: string): string | undefined => {
|
||||
const languages =
|
||||
|
||||
@@ -21,6 +21,7 @@ const getFontStyles = (
|
||||
sansSerif: string,
|
||||
monospace: string,
|
||||
defaultFont: string,
|
||||
defaultCJKFont: string,
|
||||
fontSize: number,
|
||||
minFontSize: number,
|
||||
fontWeight: number,
|
||||
@@ -28,16 +29,22 @@ const getFontStyles = (
|
||||
themeCode: ThemeCode,
|
||||
) => {
|
||||
const { primary } = themeCode;
|
||||
const lastSerifFonts = ['Georgia', 'Times New Roman'];
|
||||
const lastSerifFonts = ['LXGW WenKai GB Screen', 'Georgia', 'Times New Roman'];
|
||||
const serifFonts = [
|
||||
serif,
|
||||
...SERIF_FONTS.filter((font) => font !== serif && !lastSerifFonts.includes(font)),
|
||||
...SERIF_FONTS.filter(
|
||||
(font) => font !== serif && font !== defaultCJKFont && !lastSerifFonts.includes(font),
|
||||
),
|
||||
...(defaultCJKFont !== serif && !lastSerifFonts.includes(defaultCJKFont)
|
||||
? [defaultCJKFont]
|
||||
: []),
|
||||
...lastSerifFonts.filter((font) => SERIF_FONTS.includes(font)),
|
||||
...FALLBACK_FONTS,
|
||||
];
|
||||
const sansSerifFonts = [
|
||||
sansSerif,
|
||||
...SANS_SERIF_FONTS.filter((font) => font !== sansSerif),
|
||||
...SANS_SERIF_FONTS.filter((font) => font !== sansSerif && font !== defaultCJKFont),
|
||||
...(defaultCJKFont !== sansSerif ? [defaultCJKFont] : []),
|
||||
...FALLBACK_FONTS,
|
||||
];
|
||||
const monospaceFonts = [monospace, ...MONOSPACE_FONTS.filter((font) => font !== monospace)];
|
||||
@@ -367,6 +374,7 @@ export const getStyles = (viewSettings: ViewSettings, themeCode?: ThemeCode) =>
|
||||
viewSettings.sansSerifFont!,
|
||||
viewSettings.monospaceFont!,
|
||||
viewSettings.defaultFont!,
|
||||
viewSettings.defaultCJKFont!,
|
||||
viewSettings.defaultFontSize! * fontScale,
|
||||
viewSettings.minimumFontSize!,
|
||||
viewSettings.fontWeight!,
|
||||
|
||||
Reference in New Issue
Block a user