diff --git a/package-lock.json b/package-lock.json index 8698098..170a39a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,8 +10,10 @@ "dependencies": { "@tauri-apps/api": "^2", "@tauri-apps/plugin-opener": "^2", + "i18next": "^25.3.2", "react": "^18.3.1", - "react-dom": "^18.3.1" + "react-dom": "^18.3.1", + "react-i18next": "^15.6.0" }, "devDependencies": { "@tauri-apps/cli": "^2", @@ -271,6 +273,15 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/runtime": { + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", + "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", @@ -1977,6 +1988,46 @@ "node": ">=6.9.0" } }, + "node_modules/html-parse-stringify": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", + "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", + "license": "MIT", + "dependencies": { + "void-elements": "3.1.0" + } + }, + "node_modules/i18next": { + "version": "25.3.2", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.3.2.tgz", + "integrity": "sha512-JSnbZDxRVbphc5jiptxr3o2zocy5dEqpVm9qCGdJwRNO+9saUJS0/u4LnM/13C23fUEWxAylPqKU/NpMV/IjqA==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.6" + }, + "peerDependencies": { + "typescript": "^5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/immutable": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.3.tgz", @@ -2218,6 +2269,32 @@ "react": "^18.3.1" } }, + "node_modules/react-i18next": { + "version": "15.6.0", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.6.0.tgz", + "integrity": "sha512-W135dB0rDfiFmbMipC17nOhGdttO5mzH8BivY+2ybsQBbXvxWIwl3cmeH3T9d+YPBSJu/ouyJKFJTtkK7rJofw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.6", + "html-parse-stringify": "^3.0.1" + }, + "peerDependencies": { + "i18next": ">= 23.2.3", + "react": ">= 16.8.0", + "typescript": "^5" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, "node_modules/react-refresh": { "version": "0.17.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", @@ -2367,7 +2444,7 @@ "version": "5.6.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -2483,6 +2560,15 @@ } } }, + "node_modules/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", diff --git a/package.json b/package.json index f448593..be93cef 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,10 @@ "dependencies": { "@tauri-apps/api": "^2", "@tauri-apps/plugin-opener": "^2", + "i18next": "^25.3.2", "react": "^18.3.1", - "react-dom": "^18.3.1" + "react-dom": "^18.3.1", + "react-i18next": "^15.6.0" }, "devDependencies": { "@tauri-apps/cli": "^2", diff --git a/src/i18n.ts b/src/i18n.ts new file mode 100644 index 0000000..f89948e --- /dev/null +++ b/src/i18n.ts @@ -0,0 +1,21 @@ +import i18n from 'i18next'; +import { initReactI18next } from 'react-i18next'; + +import en from './locales/en.json'; +import jp from './locales/jp.json'; + +i18n + .use(initReactI18next) + .init({ + resources: { + en: { translation: en }, + jp: { translation: jp }, + }, + lng: 'jp', // 初期言語 + fallbackLng: 'en', + interpolation: { + escapeValue: false, + }, + }); + +export default i18n; diff --git a/src/locales/en.json b/src/locales/en.json new file mode 100644 index 0000000..2c63c08 --- /dev/null +++ b/src/locales/en.json @@ -0,0 +1,2 @@ +{ +} diff --git a/src/locales/jp.json b/src/locales/jp.json new file mode 100644 index 0000000..5be6a60 --- /dev/null +++ b/src/locales/jp.json @@ -0,0 +1,33 @@ +{ + "terms": { + "toshoGrowth": "東証グロース", + "toshoStandard": "東証スタンダード", + "toshoPrime": "東証プライム", + "stock": { + "price": "株価", + "volume": "時価総額" + } + }, + "pages": { + "screening": { + "title": "銘柄スクリーニング", + "rerun": "再実行", + "universe": { + "title": "ユニバース", + "desc": "スクリーニング対象の銘柄の条件を設定してください", + "type": { + "listed": "全上場銘柄" + } + }, + "evaluation": { + "title": "銘柄評価", + "desc": "銘柄一覧テーブルに表示する列を設定してください", + "columnName": "カラム名" + }, + "filterOut": { + "title": "選別", + "desc": "銘柄の選別条件を設定してください" + } + } + } +} diff --git a/src/main.tsx b/src/main.tsx index 2be325e..eaf5d45 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,6 +1,7 @@ import React from "react"; import ReactDOM from "react-dom/client"; import App from "./App"; +import "./i18n"; ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( diff --git a/src/pages/Screening.tsx b/src/pages/Screening.tsx index 3a2818c..11ebe5d 100644 --- a/src/pages/Screening.tsx +++ b/src/pages/Screening.tsx @@ -1,6 +1,96 @@ +import { ReactNode } from "react"; +import { useTranslation } from "react-i18next"; + function Screening() { + const {t} = useTranslation(); return ( -

SCREENING

+ <> +

{t("pages.screening.title")}

+ + + + ); } export default Screening; + +function UniverseSpec() { + const {t} = useTranslation(); + return ( + + + + + + + ); +} + +function EvaluationSpec() { + const {t} = useTranslation(); + return ( + +
    + { + [...Array(3)].map((_,i)=>( +
  1. + + = + + remove +
  2. + )) + } +
  3. + add +
  4. +
+
+ ); +} + +function FilterOutSpec() { + const {t} = useTranslation(); + return ( + +