feat: add languages

main
imspace 2023-03-13 12:00:01 +08:00
parent 772af8da0d
commit afa239df64
8 changed files with 125 additions and 6 deletions

View File

@ -10,7 +10,7 @@ const keys: Set<string> = new Set();
async function updateFile() {
delayId = null;
for (const lng of ["en", "zh-CN"]) {
for (const lng of ["en", 'ja', "zh-CN"]) {
const translationPath = path.join(
__dirname,
`../src/i18n/translation/${lng}.json`,

View File

@ -36,11 +36,12 @@ detectAndInject();
"#;
#[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(
&app,
"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")
.center()

View File

@ -35,6 +35,7 @@ export const OpenSplatnet: React.FC<OpenSplatnetProps> = ({ children }) => {
const gtoken = newState.loginState?.gToken;
await invoke('open_splatnet', {
gtoken,
lang: result.profile.state.userLang,
});
} catch (e) {
setError(e);

View File

@ -3,6 +3,7 @@ import LanguageDetector from 'i18next-browser-languagedetector';
import { initReactI18next } from 'react-i18next';
import en from './translation/en.json';
import zhCN from './translation/zh-CN.json';
import ja from './translation/ja.json';
import HttpBackend from 'i18next-http-backend'
export const resources = {
@ -11,6 +12,9 @@ export const resources = {
},
'zh-CN': {
translation: zhCN,
},
ja: {
translation: ja,
}
};
@ -25,5 +29,6 @@ if (import.meta.env.DEV) {
instance.init({
debug: import.meta.env.DEV,
resources,
fallbackLng: 'en',
// saveMissing: true,
});

View File

@ -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"
}

View File

@ -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キー"
}

View File

@ -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密钥"
}

View File

@ -27,12 +27,34 @@ type FormData = {
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<{
oldValue: FormData,
onSaved?: () => void,
}> = ({ oldValue, onSaved }) => {
const { login } = useLogin();
const { t } = useTranslation();
const { t, i18n } = useTranslation();
const [value, setValue] = useState(oldValue);
const { subField } = useSubField({ value, onChange: setValue });
@ -40,6 +62,7 @@ const Form: React.FC<{
const sessionToken = subField('profile.state.loginState.sessionToken')
const statInkApiKey = subField('profile.state.statInkApiKey')
const splatnet3Lang = subField('profile.state.userLang')
const [onSave, { loading, error }] = usePromiseLazy(async () => {
await setProfile(0, value.profile);
@ -100,6 +123,28 @@ const Form: React.FC<{
/>
</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>
<ErrorContent error={error} />
<div className='flex gap-4 max-w-md justify-between flex-auto-all'>