layout: use system select widget for language selection, closes #1339 (#1342)

This commit is contained in:
Huang Xin
2025-06-05 14:19:24 +08:00
committed by GitHub
parent debd60fb70
commit 57e22dc7b6
4 changed files with 38 additions and 29 deletions
@@ -142,6 +142,7 @@ const TranslatorPopup: React.FC<TranslatorPopupProps> = ({
<div className='mb-2 flex items-center justify-between'>
<h1 className='text-sm font-normal'>{_('Original Text')}</h1>
<Select
className='bg-gray-600 text-white/75'
value={sourceLang}
onChange={handleSourceLangChange}
options={[
@@ -168,6 +169,7 @@ const TranslatorPopup: React.FC<TranslatorPopupProps> = ({
<div className='mb-2 flex items-center justify-between'>
<h2 className='text-sm font-normal'>{_('Translated Text')}</h2>
<Select
className='bg-gray-600 text-white/75'
value={targetLang}
onChange={handleTargetLangChange}
options={Object.entries(TRANSLATOR_LANGS)
@@ -201,6 +203,7 @@ const TranslatorPopup: React.FC<TranslatorPopupProps> = ({
)}
<div className='ml-auto'>
<Select
className='bg-gray-600 text-white/75'
value={provider}
onChange={handleProviderChange}
options={providers.map(({ name: value, label }) => ({ value, label }))}
@@ -7,7 +7,7 @@ import { useTranslation } from '@/hooks/useTranslation';
import { saveViewSettings } from '../../utils/viewSettingsHelper';
import { getTranslators } from '@/services/translators';
import { TRANSLATED_LANGS } from '@/services/constants';
import DropDown from './DropDown';
import Select from '@/components/Select';
const LangPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
const _ = useTranslation();
@@ -22,7 +22,7 @@ const LangPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
const getCurrentUILangOption = () => {
const uiLanguage = viewSettings.uiLanguage;
return {
option: uiLanguage,
value: uiLanguage,
label:
uiLanguage === ''
? _('Auto')
@@ -32,13 +32,14 @@ const LangPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
const getLangOptions = () => {
const langs = TRANSLATED_LANGS as Record<string, string>;
const options = Object.entries(langs).map(([option, label]) => ({ option, label }));
const options = Object.entries(langs).map(([value, label]) => ({ value, label }));
options.sort((a, b) => a.label.localeCompare(b.label));
options.unshift({ option: '', label: _('System Language') });
options.unshift({ value: '', label: _('System Language') });
return options;
};
const handleSelectUILang = (option: string) => {
const handleSelectUILang = (event: React.ChangeEvent<HTMLSelectElement>) => {
const option = event.target.value;
saveViewSettings(envConfig, bookKey, 'uiLanguage', option, false, false);
i18n.changeLanguage(option ? option : navigator.language);
};
@@ -46,18 +47,19 @@ const LangPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
const getTranslationProviderOptions = () => {
const translators = getTranslators();
const availableProviders = translators.map((t) => {
return { option: t.name, label: t.label };
return { value: t.name, label: t.label };
});
return availableProviders;
};
const getCurrentTranslationProviderOption = () => {
const option = translationProvider;
const value = translationProvider;
const availableProviders = getTranslationProviderOptions();
return availableProviders.find((p) => p.option === option) || availableProviders[0]!;
return availableProviders.find((p) => p.value === value) || availableProviders[0]!;
};
const handleSelectTranslationProvider = (option: string) => {
const handleSelectTranslationProvider = (event: React.ChangeEvent<HTMLSelectElement>) => {
const option = event.target.value;
setTranslationProvider(option);
saveViewSettings(envConfig, bookKey, 'translationProvider', option, false, false);
viewSettings.translationProvider = option;
@@ -65,12 +67,13 @@ const LangPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
};
const getCurrentTargetLangOption = () => {
const option = translateTargetLang;
const value = translateTargetLang;
const availableOptions = getLangOptions();
return availableOptions.find((o) => o.option === option) || availableOptions[0]!;
return availableOptions.find((o) => o.value === value) || availableOptions[0]!;
};
const handleSelectTargetLang = (option: string) => {
const handleSelectTargetLang = (event: React.ChangeEvent<HTMLSelectElement>) => {
const option = event.target.value;
setTranslateTargetLang(option);
saveViewSettings(envConfig, bookKey, 'translateTargetLang', option, false, false);
viewSettings.translateTargetLang = option;
@@ -93,12 +96,10 @@ const LangPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
<div className='divide-base-200 divide-y'>
<div className='config-item'>
<span className=''>{_('Interface Language')}</span>
<DropDown
<Select
value={getCurrentUILangOption().value}
onChange={handleSelectUILang}
options={getLangOptions()}
selected={getCurrentUILangOption()}
onSelect={handleSelectUILang}
className='dropdown-bottom'
listClassName='!max-h-60'
/>
</div>
</div>
@@ -121,24 +122,21 @@ const LangPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
<div className='config-item'>
<span className=''>{_('Translation Service')}</span>
<DropDown
selected={getCurrentTranslationProviderOption()}
<Select
value={getCurrentTranslationProviderOption().value}
onChange={handleSelectTranslationProvider}
options={getTranslationProviderOptions()}
onSelect={handleSelectTranslationProvider}
disabled={!translationEnabled}
className='dropdown-top'
/>
</div>
<div className='config-item'>
<span className=''>{_('Translate To')}</span>
<DropDown
<Select
value={getCurrentTargetLangOption().value}
onChange={handleSelectTargetLang}
options={getLangOptions()}
selected={getCurrentTargetLangOption()}
onSelect={handleSelectTargetLang}
disabled={!translationEnabled}
className='dropdown-top'
listClassName='!max-h-60'
/>
</div>
</div>
+10 -2
View File
@@ -10,19 +10,27 @@ type SelectProps = {
value: string;
onChange: (e: React.ChangeEvent<HTMLSelectElement>) => void;
options: Option[];
disabled?: boolean;
className?: string;
};
export default function Select({ value, onChange, options, className }: SelectProps) {
export default function Select({
value,
onChange,
options,
className,
disabled = false,
}: SelectProps) {
return (
<select
value={value}
onChange={onChange}
className={clsx(
'select h-8 min-h-8 rounded-md border-none text-end text-sm',
'bg-gray-600 text-white/75 focus:outline-none focus:ring-0',
'focus:outline-none focus:ring-0',
className,
)}
disabled={disabled}
style={{
textAlignLast: 'end',
}}
+1 -1
View File
@@ -624,7 +624,7 @@ export const TRANSLATED_LANGS = {
pl: 'Polski',
tr: 'Türkçe',
hi: 'हिन्दी',
id: 'Bahasa Indonesia',
id: 'Indonesia',
vi: 'Tiếng Việt',
'zh-CN': '简体中文',
'zh-TW': '正體中文',