feat: add languages
parent
772af8da0d
commit
afa239df64
|
|
@ -10,7 +10,7 @@ const keys: Set<string> = new Set();
|
||||||
|
|
||||||
async function updateFile() {
|
async function updateFile() {
|
||||||
delayId = null;
|
delayId = null;
|
||||||
for (const lng of ["en", "zh-CN"]) {
|
for (const lng of ["en", 'ja', "zh-CN"]) {
|
||||||
const translationPath = path.join(
|
const translationPath = path.join(
|
||||||
__dirname,
|
__dirname,
|
||||||
`../src/i18n/translation/${lng}.json`,
|
`../src/i18n/translation/${lng}.json`,
|
||||||
|
|
|
||||||
|
|
@ -36,11 +36,12 @@ detectAndInject();
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
async fn open_splatnet(app: tauri::AppHandle, gtoken: String) -> Option<()> {
|
async fn open_splatnet(app: tauri::AppHandle, gtoken: String, lang: Option<String>) -> Option<()> {
|
||||||
|
let ui_lang = lang.unwrap_or_else(|| "en-US".to_string());
|
||||||
let _window = WindowBuilder::new(
|
let _window = WindowBuilder::new(
|
||||||
&app,
|
&app,
|
||||||
"splatnet3",
|
"splatnet3",
|
||||||
tauri::WindowUrl::App("https://api.lp1.av5ja.srv.nintendo.net/".into()),
|
tauri::WindowUrl::App(format!("https://api.lp1.av5ja.srv.nintendo.net/?lang={ui_lang}").into()),
|
||||||
)
|
)
|
||||||
.title("Splatnet3")
|
.title("Splatnet3")
|
||||||
.center()
|
.center()
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ export const OpenSplatnet: React.FC<OpenSplatnetProps> = ({ children }) => {
|
||||||
const gtoken = newState.loginState?.gToken;
|
const gtoken = newState.loginState?.gToken;
|
||||||
await invoke('open_splatnet', {
|
await invoke('open_splatnet', {
|
||||||
gtoken,
|
gtoken,
|
||||||
|
lang: result.profile.state.userLang,
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setError(e);
|
setError(e);
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import LanguageDetector from 'i18next-browser-languagedetector';
|
||||||
import { initReactI18next } from 'react-i18next';
|
import { initReactI18next } from 'react-i18next';
|
||||||
import en from './translation/en.json';
|
import en from './translation/en.json';
|
||||||
import zhCN from './translation/zh-CN.json';
|
import zhCN from './translation/zh-CN.json';
|
||||||
|
import ja from './translation/ja.json';
|
||||||
import HttpBackend from 'i18next-http-backend'
|
import HttpBackend from 'i18next-http-backend'
|
||||||
|
|
||||||
export const resources = {
|
export const resources = {
|
||||||
|
|
@ -11,6 +12,9 @@ export const resources = {
|
||||||
},
|
},
|
||||||
'zh-CN': {
|
'zh-CN': {
|
||||||
translation: zhCN,
|
translation: zhCN,
|
||||||
|
},
|
||||||
|
ja: {
|
||||||
|
translation: ja,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -25,5 +29,6 @@ if (import.meta.env.DEV) {
|
||||||
instance.init({
|
instance.init({
|
||||||
debug: import.meta.env.DEV,
|
debug: import.meta.env.DEV,
|
||||||
resources,
|
resources,
|
||||||
|
fallbackLng: 'en',
|
||||||
// saveMissing: true,
|
// saveMissing: true,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1 +1,23 @@
|
||||||
{}
|
{
|
||||||
|
"保存": "Save",
|
||||||
|
"查看API密钥": "View API Key",
|
||||||
|
"打开 stat.ink": "Open stat.ink",
|
||||||
|
"打开鱿鱼圈3": "Open Splatnet3",
|
||||||
|
"导出": "Export",
|
||||||
|
"导出打工数据": "Export Salmon Run",
|
||||||
|
"导出对战数据": "Export VS",
|
||||||
|
"欢迎! 请点击\"导出\"按钮开始使用.": "Welcome! Please click \"Export\" button to start using.",
|
||||||
|
"界面语言": "Interface Language",
|
||||||
|
"没有更改": "No changes made",
|
||||||
|
"密钥的长度应该为{{length}}, 请检查": "The length of the key should be {{length}}, please check",
|
||||||
|
"前往 stat.ink": "Go to stat.ink",
|
||||||
|
"请从stat.ink中获取API密钥": "Please obtain the API key from stat.ink",
|
||||||
|
"请点击右上角的登录填入": "Please click the top right corner to log in",
|
||||||
|
"请先在设置中完成Nintendo Account登录和stat.ink的API密钥": "Please complete Nintendo Account login and stat.ink API key setup in settings first",
|
||||||
|
"设置": "Settings",
|
||||||
|
"网页登录": "Web Login",
|
||||||
|
"鱿鱼圈3语言偏好": "Splatnet3 Language",
|
||||||
|
"重置": "Reset",
|
||||||
|
"Nintendo Account 会话令牌": "Nintendo Account Session Token",
|
||||||
|
"stat.ink API密钥": "stat.ink API Key"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"保存": "保存",
|
||||||
|
"查看API密钥": "APIキーを表示する",
|
||||||
|
"打开 stat.ink": "stat.inkを開く",
|
||||||
|
"打开鱿鱼圈3": "イカリング3を開く",
|
||||||
|
"导出": "エクスポートする",
|
||||||
|
"导出打工数据": "勤務データをエクスポートする",
|
||||||
|
"导出对战数据": "対戦データをエクスポートする",
|
||||||
|
"欢迎! 请点击\"导出\"按钮开始使用.": "ようこそ!「エクスポート」ボタンをクリックして使い始めてください。",
|
||||||
|
"界面语言": "インターフェース言語",
|
||||||
|
"没有更改": "変更はありません",
|
||||||
|
"密钥的长度应该为{{length}}, 请检查": "キーの長さは{{length}}でなければなりません。確認してください。",
|
||||||
|
"前往 stat.ink": "stat.inkに移動する",
|
||||||
|
"请从stat.ink中获取API密钥": "stat.inkからAPIキーを取得してください",
|
||||||
|
"请点击右上角的登录填入": "右上隅のログインをクリックして入力してください",
|
||||||
|
"请先在设置中完成Nintendo Account登录和stat.ink的API密钥": "Nintendoアカウントのログインとstat.inkのAPIキー設定を先に設定してください",
|
||||||
|
"设置": "設定",
|
||||||
|
"网页登录": "ウェブサイトにログインする",
|
||||||
|
"鱿鱼圈3语言偏好": "イカリング3言語設定",
|
||||||
|
"重置": "リセット",
|
||||||
|
"Nintendo Account 会话令牌": "Nintendo Accountセッショントークン",
|
||||||
|
"stat.ink API密钥": "stat.ink APIキー"
|
||||||
|
}
|
||||||
|
|
@ -1 +1,23 @@
|
||||||
{}
|
{
|
||||||
|
"保存": "保存",
|
||||||
|
"查看API密钥": "查看API密钥",
|
||||||
|
"打开 stat.ink": "打开 stat.ink",
|
||||||
|
"打开鱿鱼圈3": "打开鱿鱼圈3",
|
||||||
|
"导出": "导出",
|
||||||
|
"导出打工数据": "导出打工数据",
|
||||||
|
"导出对战数据": "导出对战数据",
|
||||||
|
"欢迎! 请点击\"导出\"按钮开始使用.": "欢迎! 请点击\"导出\"按钮开始使用.",
|
||||||
|
"界面语言": "界面语言",
|
||||||
|
"没有更改": "没有更改",
|
||||||
|
"密钥的长度应该为{{length}}, 请检查": "密钥的长度应该为{{length}}, 请检查",
|
||||||
|
"前往 stat.ink": "前往 stat.ink",
|
||||||
|
"请从stat.ink中获取API密钥": "请从stat.ink中获取API密钥",
|
||||||
|
"请点击右上角的登录填入": "请点击右上角的登录填入",
|
||||||
|
"请先在设置中完成Nintendo Account登录和stat.ink的API密钥": "请先在设置中完成Nintendo Account登录和stat.ink的API密钥",
|
||||||
|
"设置": "设置",
|
||||||
|
"网页登录": "网页登录",
|
||||||
|
"鱿鱼圈3语言偏好": "鱿鱼圈3语言偏好",
|
||||||
|
"重置": "重置",
|
||||||
|
"Nintendo Account 会话令牌": "Nintendo Account 会话令牌",
|
||||||
|
"stat.ink API密钥": "stat.ink API密钥"
|
||||||
|
}
|
||||||
|
|
@ -27,12 +27,34 @@ type FormData = {
|
||||||
profile: Profile,
|
profile: Profile,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SPLATNET3_LANGS = {
|
||||||
|
"de-DE": "German",
|
||||||
|
"en-GB": "English (UK/Australia)",
|
||||||
|
"en-US": "English (US)",
|
||||||
|
"es-ES": "Spanish (Spain)",
|
||||||
|
"es-MX": "Spanish (Latin America)",
|
||||||
|
"fr-CA": "French (Canada)",
|
||||||
|
"fr-FR": "French (France)",
|
||||||
|
"it-IT": "Italian",
|
||||||
|
"ja-JP": "Japanese",
|
||||||
|
"ko-KR": "Korean",
|
||||||
|
"nl-NL": "Dutch",
|
||||||
|
"ru-RU": "Russian",
|
||||||
|
"zh-CN": "Chinese (China)",
|
||||||
|
"zh-TW": "Chinese (Taiwan)"
|
||||||
|
}
|
||||||
|
const UI_LANGS = {
|
||||||
|
"en": "English",
|
||||||
|
"zh-CN": "简体中文",
|
||||||
|
"ja": "日本語",
|
||||||
|
};
|
||||||
|
|
||||||
const Form: React.FC<{
|
const Form: React.FC<{
|
||||||
oldValue: FormData,
|
oldValue: FormData,
|
||||||
onSaved?: () => void,
|
onSaved?: () => void,
|
||||||
}> = ({ oldValue, onSaved }) => {
|
}> = ({ oldValue, onSaved }) => {
|
||||||
const { login } = useLogin();
|
const { login } = useLogin();
|
||||||
const { t } = useTranslation();
|
const { t, i18n } = useTranslation();
|
||||||
const [value, setValue] = useState(oldValue);
|
const [value, setValue] = useState(oldValue);
|
||||||
const { subField } = useSubField({ value, onChange: setValue });
|
const { subField } = useSubField({ value, onChange: setValue });
|
||||||
|
|
||||||
|
|
@ -40,6 +62,7 @@ const Form: React.FC<{
|
||||||
|
|
||||||
const sessionToken = subField('profile.state.loginState.sessionToken')
|
const sessionToken = subField('profile.state.loginState.sessionToken')
|
||||||
const statInkApiKey = subField('profile.state.statInkApiKey')
|
const statInkApiKey = subField('profile.state.statInkApiKey')
|
||||||
|
const splatnet3Lang = subField('profile.state.userLang')
|
||||||
|
|
||||||
const [onSave, { loading, error }] = usePromiseLazy(async () => {
|
const [onSave, { loading, error }] = usePromiseLazy(async () => {
|
||||||
await setProfile(0, value.profile);
|
await setProfile(0, value.profile);
|
||||||
|
|
@ -100,6 +123,28 @@ const Form: React.FC<{
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="form-control w-full max-w-md mb-4">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">{t('鱿鱼圈3语言偏好')}</span>
|
||||||
|
</label>
|
||||||
|
<select className="select w-full" value={splatnet3Lang.value} onChange={
|
||||||
|
e => splatnet3Lang.onChange(e.target.value)
|
||||||
|
}>
|
||||||
|
{Object.entries(SPLATNET3_LANGS).map(([key, value]) => <option key={key} value={key}>{value} ({key})</option>)}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div className="form-control w-full max-w-md mb-4">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">{t('界面语言')}</span>
|
||||||
|
</label>
|
||||||
|
<select className="select w-full" value={i18n.language} onChange={
|
||||||
|
e => {
|
||||||
|
i18n.changeLanguage(e.target.value);
|
||||||
|
}
|
||||||
|
}>
|
||||||
|
{Object.entries(UI_LANGS).map(([key, value]) => <option key={key} value={key}>{value} ({key})</option>)}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ErrorContent error={error} />
|
<ErrorContent error={error} />
|
||||||
<div className='flex gap-4 max-w-md justify-between flex-auto-all'>
|
<div className='flex gap-4 max-w-md justify-between flex-auto-all'>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue