mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-19 01:40:15 +01:00
🌐 refactor: Interpolate Localization Keys (#10650)
* fix: replace string concatenation of localization keys with interpolations and add keys for unlocalized string literals * chore: update test for new localization key --------- Co-authored-by: Danny Avila <danny@librechat.ai>
This commit is contained in:
parent
39cecc97bd
commit
b6dcefc53a
28 changed files with 130 additions and 85 deletions
|
|
@ -154,9 +154,9 @@ const MarketplaceAdminSettings = () => {
|
|||
</Button>
|
||||
</OGDialogTrigger>
|
||||
<OGDialogContent className="w-11/12 max-w-md border-border-light bg-surface-primary text-text-primary">
|
||||
<OGDialogTitle>{`${localize('com_ui_admin_settings')} - ${localize(
|
||||
'com_ui_marketplace',
|
||||
)}`}</OGDialogTitle>
|
||||
<OGDialogTitle>
|
||||
{localize('com_ui_admin_settings_section', { section: localize('com_ui_marketplace') })}
|
||||
</OGDialogTitle>
|
||||
<div className="p-2">
|
||||
{/* Role selection dropdown */}
|
||||
<div className="flex items-center gap-2">
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ function MCPSelectContent() {
|
|||
const renderSelectedValues = useCallback(
|
||||
(values: string[], placeholder?: string) => {
|
||||
if (values.length === 0) {
|
||||
return placeholder || localize('com_ui_select') + '...';
|
||||
return placeholder || localize('com_ui_select_placeholder');
|
||||
}
|
||||
if (values.length === 1) {
|
||||
return values[0];
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ const EditPresetDialog = ({
|
|||
<OGDialog open={presetModalVisible} onOpenChange={handleOpenChange}>
|
||||
<OGDialogContent className="h-[100dvh] max-h-[100dvh] w-full max-w-full overflow-y-auto bg-white dark:border-gray-700 dark:bg-gray-850 dark:text-gray-300 md:h-auto md:max-h-[90vh] md:max-w-[75vw] md:rounded-lg lg:max-w-[950px]">
|
||||
<OGDialogTitle>
|
||||
{`${localize('com_ui_edit')} ${localize('com_endpoint_preset')} - ${preset?.title}`}
|
||||
{localize('com_ui_edit_preset_title', { title: preset?.title })}
|
||||
</OGDialogTitle>
|
||||
|
||||
<div className="flex w-full flex-col gap-2 px-1 pb-4 md:gap-4">
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ const PresetItems: FC<{
|
|||
<button
|
||||
type="button"
|
||||
className="mr-1 flex h-[32px] cursor-pointer items-center rounded bg-transparent px-2 py-1 text-xs font-medium text-gray-600 transition-colors hover:bg-gray-100 hover:text-red-700 focus:ring-ring dark:bg-transparent dark:text-gray-300 dark:hover:bg-gray-700 dark:hover:text-red-700"
|
||||
aria-label={localize('com_ui_clear') + ' ' + localize('com_ui_all')}
|
||||
aria-label={localize('com_ui_clear_all')}
|
||||
>
|
||||
<svg
|
||||
width="24"
|
||||
|
|
@ -76,12 +76,12 @@ const PresetItems: FC<{
|
|||
>
|
||||
<path d="M9.293 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V4.707A1 1 0 0 0 13.707 4L10 .293A1 1 0 0 0 9.293 0M9.5 3.5v-2l3 3h-2a1 1 0 0 1-1-1M6.854 7.146 8 8.293l1.146-1.147a.5.5 0 1 1 .708.708L8.707 9l1.147 1.146a.5.5 0 0 1-.708.708L8 9.707l-1.146 1.147a.5.5 0 0 1-.708-.708L7.293 9 6.146 7.854a.5.5 0 1 1 .708-.708"></path>
|
||||
</svg>
|
||||
{localize('com_ui_clear')} {localize('com_ui_all')}
|
||||
{localize('com_ui_clear_all')}
|
||||
</button>
|
||||
</DialogTrigger>
|
||||
<DialogTemplate
|
||||
showCloseButton={false}
|
||||
title={`${localize('com_ui_clear')} ${localize('com_endpoint_presets')}`}
|
||||
title={localize('com_ui_clear_presets')}
|
||||
className="max-w-[450px]"
|
||||
main={
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -137,7 +137,9 @@ export default function Conversation({ conversation, retainView, toggleNav }: Co
|
|||
)}
|
||||
role="button"
|
||||
tabIndex={renaming ? -1 : 0}
|
||||
aria-label={`${title || localize('com_ui_untitled')} conversation`}
|
||||
aria-label={localize('com_ui_conversation_label', {
|
||||
title: title || localize('com_ui_untitled'),
|
||||
})}
|
||||
onClick={(e) => {
|
||||
if (renaming) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import React, { useCallback } from 'react';
|
||||
import { Trans } from 'react-i18next';
|
||||
import { QueryKeys } from 'librechat-data-provider';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
|
|
@ -80,7 +81,7 @@ export function DeleteConversationDialog({
|
|||
|
||||
return (
|
||||
<OGDialogContent
|
||||
title={localize('com_ui_delete_confirm') + ' ' + title}
|
||||
title={localize('com_ui_delete_confirm', { title })}
|
||||
className="w-11/12 max-w-md"
|
||||
showCloseButton={false}
|
||||
>
|
||||
|
|
@ -88,7 +89,11 @@ export function DeleteConversationDialog({
|
|||
<OGDialogTitle>{localize('com_ui_delete_conversation')}</OGDialogTitle>
|
||||
</OGDialogHeader>
|
||||
<div className="w-full truncate">
|
||||
{localize('com_ui_delete_confirm')} <strong>{title}</strong> ?
|
||||
<Trans
|
||||
i18nKey="com_ui_delete_confirm_strong"
|
||||
values={{ item: title }}
|
||||
components={{ strong: <strong /> }}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex justify-end gap-4 pt-4">
|
||||
<Button aria-label="cancel" variant="outline" onClick={() => setShowDeleteDialog(false)}>
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ const SearchBar = forwardRef((props: SearchBarProps, ref: React.Ref<HTMLDivEleme
|
|||
/>
|
||||
<button
|
||||
type="button"
|
||||
aria-label={`${localize('com_ui_clear')} ${localize('com_ui_search')}`}
|
||||
aria-label={localize('com_ui_clear_search')}
|
||||
className={cn(
|
||||
'absolute right-[7px] flex h-5 w-5 items-center justify-center rounded-full border-none bg-transparent p-0 transition-opacity duration-200',
|
||||
showClearIcon ? 'opacity-100' : 'opacity-0',
|
||||
|
|
|
|||
|
|
@ -19,12 +19,12 @@ const ChatDirection = () => {
|
|||
</div>
|
||||
<Button
|
||||
variant="outline"
|
||||
aria-label={`${localize('com_nav_chat_direction')}: ${localize('com_ui_x_selected', {
|
||||
0:
|
||||
aria-label={localize('com_nav_chat_direction_selected', {
|
||||
direction:
|
||||
direction === 'LTR'
|
||||
? localize('chat_direction_left_to_right')
|
||||
: localize('chat_direction_right_to_left'),
|
||||
})}`}
|
||||
})}
|
||||
onClick={toggleChatDirection}
|
||||
data-testid="chatDirection"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -251,7 +251,9 @@ export default function SharedLinks() {
|
|||
onClick={() => {
|
||||
window.open(`/c/${row.original.conversationId}`, '_blank');
|
||||
}}
|
||||
aria-label={`${localize('com_ui_view_source')} - ${row.original.title || localize('com_ui_untitled')}`}
|
||||
aria-label={localize('com_ui_view_source', {
|
||||
title: row.original.title || localize('com_ui_untitled'),
|
||||
})}
|
||||
>
|
||||
<MessageSquare className="size-4" aria-hidden="true" />
|
||||
</Button>
|
||||
|
|
@ -262,7 +264,9 @@ export default function SharedLinks() {
|
|||
setDeleteRow(row.original);
|
||||
setIsDeleteOpen(true);
|
||||
}}
|
||||
aria-label={`${localize('com_ui_delete')} - ${row.original.title || localize('com_ui_untitled')}`}
|
||||
aria-label={localize('com_ui_delete_shared_link', {
|
||||
title: row.original.title || localize('com_ui_untitled'),
|
||||
})}
|
||||
>
|
||||
<TrashIcon className="size-4" aria-hidden="true" />
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { useState, useCallback, useMemo, useEffect } from 'react';
|
||||
import { Trans } from 'react-i18next';
|
||||
import debounce from 'lodash/debounce';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { TrashIcon, ArchiveRestore, ArrowUp, ArrowDown, ArrowUpDown } from 'lucide-react';
|
||||
|
|
@ -287,12 +288,18 @@ export default function ArchivedChatsTable({
|
|||
|
||||
<OGDialog open={isDeleteOpen} onOpenChange={onOpenChange}>
|
||||
<OGDialogContent
|
||||
title={localize('com_ui_delete_confirm') + ' ' + (deleteConversation?.title ?? '')}
|
||||
title={localize('com_ui_delete_confirm', {
|
||||
title: deleteConversation?.title ?? localize('com_ui_untitled'),
|
||||
})}
|
||||
className="w-11/12 max-w-md"
|
||||
>
|
||||
<OGDialogHeader>
|
||||
<OGDialogTitle>
|
||||
{localize('com_ui_delete_confirm')} <strong>{deleteConversation?.title}</strong>
|
||||
<Trans
|
||||
i18nKey="com_ui_delete_confirm_strong"
|
||||
values={{ title: deleteConversation?.title }}
|
||||
components={{ strong: <strong /> }}
|
||||
/>
|
||||
</OGDialogTitle>
|
||||
</OGDialogHeader>
|
||||
<div className="flex justify-end gap-4 pt-4">
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ const AdminSettings = () => {
|
|||
</OGDialogTrigger>
|
||||
<OGDialogContent className="max-w-lg border-border-light bg-surface-primary text-text-primary lg:w-1/4">
|
||||
<OGDialogTitle>
|
||||
{`${localize('com_ui_admin_settings')} - ${localize('com_ui_prompts')}`}
|
||||
{localize('com_ui_admin_settings_section', { section: localize('com_ui_prompts') })}
|
||||
</OGDialogTitle>
|
||||
<div className="p-2">
|
||||
{/* Role selection dropdown */}
|
||||
|
|
|
|||
|
|
@ -72,11 +72,7 @@ function ChatGroupItem({
|
|||
<button
|
||||
id={`prompt-actions-${group._id}`}
|
||||
type="button"
|
||||
aria-label={
|
||||
localize('com_ui_sr_actions_menu', { 0: group.name }) +
|
||||
' ' +
|
||||
localize('com_ui_prompt')
|
||||
}
|
||||
aria-label={localize('com_ui_sr_actions_menu', { name: group.name })}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ function DashGroupItemComponent({ group, instanceProjectId }: DashGroupItemProps
|
|||
variant="ghost"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className="h-8 w-8 p-0 hover:bg-surface-hover"
|
||||
aria-label={localize('com_ui_rename_prompt') + ' ' + group.name}
|
||||
aria-label={localize('com_ui_rename_prompt_name', { name: group.name })}
|
||||
>
|
||||
<Pen className="icon-sm text-text-primary" aria-hidden="true" />
|
||||
</Button>
|
||||
|
|
@ -130,7 +130,7 @@ function DashGroupItemComponent({ group, instanceProjectId }: DashGroupItemProps
|
|||
value={nameInputValue}
|
||||
onChange={(e) => setNameInputValue(e.target.value)}
|
||||
className="w-full"
|
||||
aria-label={localize('com_ui_rename_prompt') + ' ' + group.name}
|
||||
aria-label={localize('com_ui_rename_prompt_name', { name: group.name })}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -153,7 +153,7 @@ function DashGroupItemComponent({ group, instanceProjectId }: DashGroupItemProps
|
|||
variant="ghost"
|
||||
className="h-8 w-8 p-0 hover:bg-surface-hover"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
aria-label={localize('com_ui_delete_prompt') + ' ' + group.name}
|
||||
aria-label={localize('com_ui_delete_prompt_name', { name: group.name })}
|
||||
>
|
||||
<TrashIcon className="icon-sm text-text-primary" aria-hidden="true" />
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -42,10 +42,7 @@ export default function VariablesDropdown({
|
|||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={className}
|
||||
title={`${localize('com_ui_add')} ${localize('com_ui_special_variables')}`}
|
||||
>
|
||||
<div className={className} title={localize('com_ui_add_special_variables')}>
|
||||
<DropdownPopup
|
||||
portal={true}
|
||||
mountByState={true}
|
||||
|
|
@ -56,7 +53,7 @@ export default function VariablesDropdown({
|
|||
trigger={
|
||||
<Menu.MenuButton
|
||||
id="variables-menu-button"
|
||||
aria-label={`${localize('com_ui_add')} ${localize('com_ui_special_variables')}`}
|
||||
aria-label={localize('com_ui_add_special_variables')}
|
||||
className="flex h-8 items-center gap-1 rounded-md border border-border-medium bg-surface-secondary px-2 py-0 text-sm text-text-primary transition-colors duration-200 hover:bg-surface-tertiary"
|
||||
>
|
||||
<PlusCircle className="mr-1 h-3 w-3 text-text-secondary" aria-hidden={true} />
|
||||
|
|
|
|||
|
|
@ -166,9 +166,9 @@ const PeoplePickerAdminSettings = () => {
|
|||
</Button>
|
||||
</OGDialogTrigger>
|
||||
<OGDialogContent className="w-full border-border-light bg-surface-primary text-text-primary lg:w-1/4">
|
||||
<OGDialogTitle>{`${localize('com_ui_admin_settings')} - ${localize(
|
||||
'com_ui_people_picker',
|
||||
)}`}</OGDialogTitle>
|
||||
<OGDialogTitle>
|
||||
{localize('com_ui_admin_settings_section', { section: localize('com_ui_people_picker') })}
|
||||
</OGDialogTitle>
|
||||
<div className="p-2">
|
||||
{/* Role selection dropdown */}
|
||||
<div className="flex items-center gap-2">
|
||||
|
|
|
|||
|
|
@ -160,9 +160,9 @@ const AdminSettings = () => {
|
|||
</Button>
|
||||
</OGDialogTrigger>
|
||||
<OGDialogContent className="border-border-light bg-surface-primary text-text-primary lg:w-1/4">
|
||||
<OGDialogTitle>{`${localize('com_ui_admin_settings')} - ${localize(
|
||||
'com_ui_agents',
|
||||
)}`}</OGDialogTitle>
|
||||
<OGDialogTitle>
|
||||
{localize('com_ui_admin_settings_section', { section: localize('com_ui_agents') })}
|
||||
</OGDialogTitle>
|
||||
<div className="p-2">
|
||||
{/* Role selection dropdown */}
|
||||
<div className="flex items-center gap-2">
|
||||
|
|
|
|||
|
|
@ -315,9 +315,18 @@ export default function AgentConfig() {
|
|||
{/* Agent Tools & Actions */}
|
||||
<div className="mb-4">
|
||||
<label className={labelClass}>
|
||||
{`${toolsEnabled === true ? localize('com_ui_tools') : ''}
|
||||
${toolsEnabled === true && actionsEnabled === true ? ' + ' : ''}
|
||||
${actionsEnabled === true ? localize('com_assistants_actions') : ''}`}
|
||||
{(() => {
|
||||
if (toolsEnabled === true && actionsEnabled === true) {
|
||||
return localize('com_ui_tools_and_actions');
|
||||
}
|
||||
if (toolsEnabled === true) {
|
||||
return localize('com_ui_tools');
|
||||
}
|
||||
if (actionsEnabled === true) {
|
||||
return localize('com_assistants_actions');
|
||||
}
|
||||
return '';
|
||||
})()}
|
||||
</label>
|
||||
<div>
|
||||
<div className="mb-1">
|
||||
|
|
|
|||
|
|
@ -335,7 +335,8 @@ describe('AgentPanel - Update Agent Toast Messages', () => {
|
|||
|
||||
await waitFor(() => {
|
||||
expect(mockShowToast).toHaveBeenCalledWith({
|
||||
message: 'com_assistants_update_success Test Agent',
|
||||
message: 'com_assistants_update_success_name',
|
||||
status: undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -355,7 +356,8 @@ describe('AgentPanel - Update Agent Toast Messages', () => {
|
|||
|
||||
await waitFor(() => {
|
||||
expect(mockShowToast).toHaveBeenCalledWith({
|
||||
message: 'com_assistants_update_success com_ui_agent',
|
||||
message: 'com_assistants_update_success_name',
|
||||
status: undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -375,7 +377,8 @@ describe('AgentPanel - Update Agent Toast Messages', () => {
|
|||
|
||||
await waitFor(() => {
|
||||
expect(mockShowToast).toHaveBeenCalledWith({
|
||||
message: 'com_assistants_update_success Test Agent',
|
||||
message: 'com_assistants_update_success_name',
|
||||
status: undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ function getUpdateToastMessage(
|
|||
if (noVersionChange) {
|
||||
return localize('com_ui_no_changes');
|
||||
}
|
||||
return `${localize('com_assistants_update_success')} ${name ?? localize('com_ui_agent')}`;
|
||||
return localize('com_assistants_update_success_name', { name: name ?? localize('com_ui_agent') });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -504,20 +504,10 @@ export default function AgentPanel() {
|
|||
setCurrentAgentId(undefined);
|
||||
}}
|
||||
disabled={agentQuery.isInitialLoading}
|
||||
aria-label={
|
||||
localize('com_ui_create') +
|
||||
' ' +
|
||||
localize('com_ui_new') +
|
||||
' ' +
|
||||
localize('com_ui_agent')
|
||||
}
|
||||
aria-label={localize('com_ui_create_new_agent')}
|
||||
>
|
||||
<Plus className="mr-1 h-4 w-4" aria-hidden="true" />
|
||||
{localize('com_ui_create') +
|
||||
' ' +
|
||||
localize('com_ui_new') +
|
||||
' ' +
|
||||
localize('com_ui_agent')}
|
||||
{localize('com_ui_create_new_agent')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="submit"
|
||||
|
|
@ -526,7 +516,7 @@ export default function AgentPanel() {
|
|||
e.preventDefault();
|
||||
handleSelectAgent();
|
||||
}}
|
||||
aria-label={localize('com_ui_select') + ' ' + localize('com_ui_agent')}
|
||||
aria-label={localize('com_ui_select_agent')}
|
||||
>
|
||||
{localize('com_ui_select')}
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ export default function AgentSelect({
|
|||
};
|
||||
}, [selectedAgentId, agents, onSelect]);
|
||||
|
||||
const createAgent = localize('com_ui_create') + ' ' + localize('com_ui_agent');
|
||||
const createAgent = localize('com_ui_create_new_agent');
|
||||
|
||||
return (
|
||||
<Controller
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ export default function DeleteButton({
|
|||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
aria-label={localize('com_ui_delete') + ' ' + localize('com_ui_agent')}
|
||||
aria-label={localize('com_ui_delete_agent')}
|
||||
type="button"
|
||||
>
|
||||
<div className="flex w-full items-center justify-center gap-2 text-red-500">
|
||||
|
|
@ -96,7 +96,7 @@ export default function DeleteButton({
|
|||
</Button>
|
||||
</OGDialogTrigger>
|
||||
<OGDialogTemplate
|
||||
title={localize('com_ui_delete') + ' ' + localize('com_ui_agent')}
|
||||
title={localize('com_ui_delete_agent')}
|
||||
className="max-w-[450px]"
|
||||
main={
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ export default function DuplicateAgent({ agent_id }: { agent_id: string }) {
|
|||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
aria-label={localize('com_ui_duplicate') + ' ' + localize('com_ui_agent')}
|
||||
aria-label={localize('com_ui_duplicate_agent')}
|
||||
type="button"
|
||||
onClick={handleDuplicate}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -263,7 +263,7 @@ export default function AssistantSelect({
|
|||
};
|
||||
}, [selectedAssistant, query.data, onSelect]);
|
||||
|
||||
const createAssistant = localize('com_ui_create') + ' ' + localize('com_ui_assistant');
|
||||
const createAssistant = localize('com_ui_create_assistant');
|
||||
return (
|
||||
<SelectDropDown
|
||||
value={!value ? createAssistant : value}
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ export default function ContextButton({
|
|||
</button>
|
||||
</DialogTrigger>
|
||||
<DialogTemplate
|
||||
title={localize('com_ui_delete') + ' ' + localize('com_ui_assistant')}
|
||||
title={localize('com_ui_delete_assistant')}
|
||||
className="max-w-[450px]"
|
||||
main={
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ function MCPPanelContent() {
|
|||
variant="outline"
|
||||
className="flex-1 justify-start dark:hover:bg-gray-700"
|
||||
onClick={() => handleServerClickToEdit(server.serverName)}
|
||||
aria-label={localize('com_ui_edit') + ' ' + server.serverName}
|
||||
aria-label={localize('com_ui_edit_server', { serverName: server.serverName })}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<span>{server.serverName}</span>
|
||||
|
|
|
|||
|
|
@ -149,9 +149,9 @@ const AdminSettings = () => {
|
|||
</Button>
|
||||
</OGDialogTrigger>
|
||||
<OGDialogContent className="border-border-light bg-surface-primary text-text-primary lg:w-1/4">
|
||||
<OGDialogTitle>{`${localize('com_ui_admin_settings')} - ${localize(
|
||||
'com_ui_memories',
|
||||
)}`}</OGDialogTitle>
|
||||
<OGDialogTitle>
|
||||
{localize('com_ui_admin_settings_section', { section: localize('com_ui_memories') })}
|
||||
</OGDialogTitle>
|
||||
<div className="p-2">
|
||||
{/* Role selection dropdown */}
|
||||
<div className="flex items-center gap-2">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue