|
@@ -1,5 +1,10 @@
|
|
|
import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit';
|
|
|
import { fetchI18nMessages, I18nMessages } from '../API/i18n/i18nActions';
|
|
|
+import {
|
|
|
+ getLanguageList,
|
|
|
+ changeLanguage,
|
|
|
+ LanguageItem,
|
|
|
+} from '../API/language';
|
|
|
|
|
|
export interface I18nState {
|
|
|
messages: I18nMessages;
|
|
@@ -7,6 +12,12 @@ export interface I18nState {
|
|
|
supportedLocales: string[];
|
|
|
loading: boolean;
|
|
|
error: string | null;
|
|
|
+ // 语言管理相关状态
|
|
|
+ availableLanguages: LanguageItem[];
|
|
|
+ selectedLanguage: string;
|
|
|
+ languagesLoading: boolean;
|
|
|
+ savingLanguage: boolean;
|
|
|
+ languageError: string | null;
|
|
|
}
|
|
|
|
|
|
const initialState: I18nState = {
|
|
@@ -15,6 +26,12 @@ const initialState: I18nState = {
|
|
|
supportedLocales: ['en', 'zh'],
|
|
|
loading: false,
|
|
|
error: null,
|
|
|
+ // 语言管理初始状态
|
|
|
+ availableLanguages: [],
|
|
|
+ selectedLanguage: '',
|
|
|
+ languagesLoading: false,
|
|
|
+ savingLanguage: false,
|
|
|
+ languageError: null,
|
|
|
};
|
|
|
|
|
|
// 异步thunk:加载多语言资源
|
|
@@ -26,6 +43,30 @@ export const loadI18nMessages = createAsyncThunk(
|
|
|
}
|
|
|
);
|
|
|
|
|
|
+// 异步thunk:加载可用语言列表
|
|
|
+export const loadAvailableLanguages = createAsyncThunk(
|
|
|
+ 'i18n/loadAvailableLanguages',
|
|
|
+ async () => {
|
|
|
+ const response = await getLanguageList();
|
|
|
+ if (response.data.code === '0x000000') {
|
|
|
+ return response.data.data;
|
|
|
+ }
|
|
|
+ throw new Error(response.data.description || '加载语言列表失败');
|
|
|
+ }
|
|
|
+);
|
|
|
+
|
|
|
+// 异步thunk:更新系统语言
|
|
|
+export const updateSystemLanguage = createAsyncThunk(
|
|
|
+ 'i18n/updateSystemLanguage',
|
|
|
+ async (language: string) => {
|
|
|
+ const response = await changeLanguage(language);
|
|
|
+ if (response.data.code === '0x000000') {
|
|
|
+ return language;
|
|
|
+ }
|
|
|
+ throw new Error(response.data.description || '修改语言失败');
|
|
|
+ }
|
|
|
+);
|
|
|
+
|
|
|
const i18nSlice = createSlice({
|
|
|
name: 'i18n',
|
|
|
initialState,
|
|
@@ -36,9 +77,18 @@ const i18nSlice = createSlice({
|
|
|
clearError: (state) => {
|
|
|
state.error = null;
|
|
|
},
|
|
|
+ // 设置选中的语言
|
|
|
+ setSelectedLanguage: (state, action: PayloadAction<string>) => {
|
|
|
+ state.selectedLanguage = action.payload;
|
|
|
+ },
|
|
|
+ // 清除语言错误
|
|
|
+ clearLanguageError: (state) => {
|
|
|
+ state.languageError = null;
|
|
|
+ },
|
|
|
},
|
|
|
extraReducers: (builder) => {
|
|
|
builder
|
|
|
+ // 加载多语言资源
|
|
|
.addCase(loadI18nMessages.pending, (state) => {
|
|
|
state.loading = true;
|
|
|
state.error = null;
|
|
@@ -51,9 +101,45 @@ const i18nSlice = createSlice({
|
|
|
.addCase(loadI18nMessages.rejected, (state, action) => {
|
|
|
state.loading = false;
|
|
|
state.error = action.error.message || 'Failed to load i18n messages';
|
|
|
+ })
|
|
|
+ // 加载可用语言列表
|
|
|
+ .addCase(loadAvailableLanguages.pending, (state) => {
|
|
|
+ state.languagesLoading = true;
|
|
|
+ state.languageError = null;
|
|
|
+ })
|
|
|
+ .addCase(loadAvailableLanguages.fulfilled, (state, action) => {
|
|
|
+ state.languagesLoading = false;
|
|
|
+ state.availableLanguages = action.payload;
|
|
|
+ // 默认选中第一个语言
|
|
|
+ if (action.payload.length > 0 && !state.selectedLanguage) {
|
|
|
+ state.selectedLanguage = action.payload[0].language;
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .addCase(loadAvailableLanguages.rejected, (state, action) => {
|
|
|
+ state.languagesLoading = false;
|
|
|
+ state.languageError =
|
|
|
+ action.error.message || '加载语言列表失败';
|
|
|
+ })
|
|
|
+ // 更新系统语言
|
|
|
+ .addCase(updateSystemLanguage.pending, (state) => {
|
|
|
+ state.savingLanguage = true;
|
|
|
+ state.languageError = null;
|
|
|
+ })
|
|
|
+ .addCase(updateSystemLanguage.fulfilled, (state, action) => {
|
|
|
+ state.savingLanguage = false;
|
|
|
+ state.currentLocale = action.payload;
|
|
|
+ })
|
|
|
+ .addCase(updateSystemLanguage.rejected, (state, action) => {
|
|
|
+ state.savingLanguage = false;
|
|
|
+ state.languageError = action.error.message || '修改语言失败';
|
|
|
});
|
|
|
},
|
|
|
});
|
|
|
|
|
|
-export const { setCurrentLocale, clearError } = i18nSlice.actions;
|
|
|
+export const {
|
|
|
+ setCurrentLocale,
|
|
|
+ clearError,
|
|
|
+ setSelectedLanguage,
|
|
|
+ clearLanguageError,
|
|
|
+} = i18nSlice.actions;
|
|
|
export default i18nSlice.reducer;
|