From 8a50ef4ef2f6f6044d36ea2f4fe06e663083972e Mon Sep 17 00:00:00 2001 From: Haishan Date: Sun, 6 Dec 2020 14:57:59 +0800 Subject: feat: initial Chinese UI language support --- src/app.tsx | 1 + src/components/Config.module.css | 6 +++- src/components/Config.tsx | 51 +++++++++++++++++++-------- src/components/Connections.tsx | 10 ++++-- src/components/Home.tsx | 4 ++- src/components/Logs.tsx | 8 +++-- src/components/Rules.tsx | 5 ++- src/components/SideBar.module.css | 1 + src/components/SideBar.tsx | 8 +++-- src/components/TrafficChart.tsx | 12 ++++--- src/components/TrafficNow.tsx | 14 ++++---- src/components/proxies/Proxies.tsx | 9 +++-- src/components/proxies/Settings.tsx | 24 +++++++------ src/components/shared/Select.module.css | 1 + src/custom.d.ts | 4 +++ src/i18n/en.ts | 34 ++++++++++++++++++ src/i18n/zh.ts | 34 ++++++++++++++++++ src/misc/i18n.ts | 61 +++++++++++++++++++++++++++++++++ 18 files changed, 238 insertions(+), 49 deletions(-) create mode 100644 src/i18n/en.ts create mode 100644 src/i18n/zh.ts create mode 100644 src/misc/i18n.ts (limited to 'src') diff --git a/src/app.tsx b/src/app.tsx index b4cc818..5d2f226 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,4 +1,5 @@ import 'modern-normalize/modern-normalize.css'; +import './misc/i18n'; import React from 'react'; import ReactDOM from 'react-dom'; diff --git a/src/components/Config.module.css b/src/components/Config.module.css index d7fa40a..1f71765 100644 --- a/src/components/Config.module.css +++ b/src/components/Config.module.css @@ -11,7 +11,7 @@ .section { padding: 6px 15px 15px; @media (--breakpoint-not-small) { - padding: 10px 40px 40px; + padding: 0 40px 40px; } } @@ -28,3 +28,7 @@ .label { padding: 16px 0; } + +.narrow { + width: 360px; +} diff --git a/src/components/Config.tsx b/src/components/Config.tsx index 981eae1..4659e16 100644 --- a/src/components/Config.tsx +++ b/src/components/Config.tsx @@ -1,5 +1,8 @@ -import PropTypes from 'prop-types'; -import React from 'react'; +import * as React from 'react'; +import { useTranslation } from 'react-i18next'; +import Select from 'src/components/shared/Select'; +import { ClashGeneralConfig, DispatchFn, State } from 'src/store/types'; +import { ClashAPIConfig } from 'src/types'; import { getClashAPIConfig, @@ -67,12 +70,17 @@ const portFields = [ { key: 'redir-port', label: 'Redir Port' }, ]; -const mapState = (s) => ({ +const langOptions = [ + ['zh', '中文'], + ['en', 'English'], +]; + +const mapState = (s: State) => ({ configs: getConfigs(s), apiConfig: getClashAPIConfig(s), }); -const mapState2 = (s) => ({ +const mapState2 = (s: State) => ({ selectedChartStyleIndex: getSelectedChartStyleIndex(s), latencyTestUrl: getLatencyTestUrl(s), apiConfig: getClashAPIConfig(s), @@ -88,13 +96,21 @@ function ConfigContainer({ dispatch, configs, apiConfig }) { return ; } +type ConfigImplProps = { + dispatch: DispatchFn; + configs: ClashGeneralConfig; + selectedChartStyleIndex: number; + latencyTestUrl: string; + apiConfig: ClashAPIConfig; +}; + function ConfigImpl({ dispatch, configs, selectedChartStyleIndex, latencyTestUrl, apiConfig, -}) { +}: ConfigImplProps) { const [configState, setConfigStateInternal] = useState(configs); const refConfigs = useRef(configs); useEffect(() => { @@ -188,9 +204,11 @@ function ConfigImpl({ return typeof m === 'string' && m[0].toUpperCase() + m.slice(1); }, [configState.mode]); + const { t, i18n } = useTranslation(); + return (
- +
{portFields.map((f) => configState[f.key] !== undefined ? ( @@ -242,7 +260,7 @@ function ConfigImpl({
-
Chart Style
+
{t('chart_style')}
-
-
Latency Test URL
+
+
{t('latency_test_url')}
Action
+
+
{t('lang')}
+
+ { + return [o[0], t(o[1])]; + })} selected={appConfig.proxySortBy} onChange={handleProxySortByOnChange} /> @@ -52,7 +56,7 @@ function Settings({ appConfig }) {

- Hide unavailable proxies + {t('hide_unavail_proxies')}
- Automatically close old connections + {t('auto_close_conns')}
void; + +i18next + .use(HttpBackend) + .use(initReactI18next) + .use(LanguageDetector) + .init({ + debug: process.env.NODE_ENV === 'development', + // resources, + backend: { + loadPath: '/__{{lng}}/{{ns}}.json', + request: function ( + _options: any, + url: string, + _payload: any, + callback: BackendRequestCallback + ) { + let p: PromiseLike<{ data: any }>; + + switch (url) { + case '/__zh/translation.json': + p = allLocales.zh; + break; + case '/__en/translation.json': + default: + p = allLocales.en; + break; + } + + if (p) { + p.then((mod) => { + callback(null, { status: 200, data: mod.data }); + }); + } + }, + }, + supportedLngs: ['en', 'zh'], + fallbackLng: 'en', + interpolation: { + escapeValue: false, + }, + }); + +if (process.env.NODE_ENV === 'development') { + window.i18n = i18next; +} + +export default i18next; -- cgit v1.3.1