feat(desktop): add i18n infrastructure with react-intl (#8105)

This commit is contained in:
jh-block
2026-03-27 19:39:50 +01:00
committed by GitHub
parent d596113e72
commit a6765fbcd9
172 changed files with 13793 additions and 2054 deletions
@@ -8,13 +8,34 @@ import {
getModelDisplayName,
getProviderDisplayName,
} from './settings/models/predefinedModelsUtils';
import { defineMessages, useIntl } from '../i18n';
export const UNKNOWN_PROVIDER_TITLE = 'Provider name lookup';
export const UNKNOWN_PROVIDER_MSG = 'Unknown provider in config -- please inspect your config.yaml';
// success
const CHANGE_MODEL_TOAST_TITLE = 'Model changed';
const SWITCH_MODEL_SUCCESS_MSG = 'Successfully switched models';
const i18n = defineMessages({
unknownProviderTitle: {
id: 'modelAndProviderContext.unknownProviderTitle',
defaultMessage: 'Provider name lookup',
},
unknownProviderMsg: {
id: 'modelAndProviderContext.unknownProviderMsg',
defaultMessage: 'Unknown provider in config -- please inspect your config.yaml',
},
modelChangedTitle: {
id: 'modelAndProviderContext.modelChangedTitle',
defaultMessage: 'Model changed',
},
switchModelSuccess: {
id: 'modelAndProviderContext.switchModelSuccess',
defaultMessage: 'Successfully switched models -- using {model} from {provider}',
},
modelChangeFailed: {
id: 'modelAndProviderContext.modelChangeFailed',
defaultMessage: '{provider}/{model} failed',
},
selectModel: {
id: 'modelAndProviderContext.selectModel',
defaultMessage: 'Select Model',
},
});
interface ModelAndProviderContextType {
currentModel: string | null;
@@ -34,10 +55,13 @@ interface ModelAndProviderProviderProps {
const ModelAndProviderContext = createContext<ModelAndProviderContextType | undefined>(undefined);
export { i18n as modelAndProviderMessages };
export const ModelAndProviderProvider: React.FC<ModelAndProviderProviderProps> = ({ children }) => {
const [currentModel, setCurrentModel] = useState<string | null>(null);
const [currentProvider, setCurrentProvider] = useState<string | null>(null);
const { read, getProviders } = useConfig();
const intl = useIntl();
const changeModel = useCallback(async (sessionId: string | null, model: Model) => {
const modelName = model.name;
@@ -79,20 +103,23 @@ export const ModelAndProviderProvider: React.FC<ModelAndProviderProviderProps> =
}
toastSuccess({
title: CHANGE_MODEL_TOAST_TITLE,
msg: `${SWITCH_MODEL_SUCCESS_MSG} -- using ${model.alias ?? modelName} from ${model.subtext ?? providerName}`,
title: intl.formatMessage(i18n.modelChangedTitle),
msg: intl.formatMessage(i18n.switchModelSuccess, {
model: model.alias ?? modelName,
provider: model.subtext ?? providerName,
}),
});
return true;
} catch (error) {
console.error(`Failed to change model at ${phase} step -- ${modelName} ${providerName}`);
toastError({
title: `${providerName}/${modelName} failed`,
title: intl.formatMessage(i18n.modelChangeFailed, { provider: providerName, model: modelName }),
msg: `${error}`,
traceback: errorMessage(error),
});
return false;
}
}, []);
}, [intl]);
const getFallbackModelAndProvider = useCallback(async () => {
const provider = window.appConfig.get('GOOSE_DEFAULT_PROVIDER') as string;
@@ -154,9 +181,9 @@ export const ModelAndProviderProvider: React.FC<ModelAndProviderProviderProps> =
const currentModelName = (await read('GOOSE_MODEL', false)) as string;
return getModelDisplayName(currentModelName);
} catch {
return 'Select Model';
return intl.formatMessage(i18n.selectModel);
}
}, [read]);
}, [read, intl]);
const getCurrentProviderDisplayName = useCallback(async () => {
try {