fix(web): update Russian translations for various components
CI / changes (push) Successful in 8s
CI / commitlint (push) Skipped
CI / go (push) Skipped
CI / bird2 (push) Skipped
CI / openapi (push) Successful in 38s
CI / web (push) Successful in 56s
CI / release (push) Successful in 4m4s

Обновлены переводы на русский язык для компонентов, включая карточки мониторинга, сетевые панели и настройки. Исправлены описания и метки для улучшения пользовательского интерфейса, а также добавлены новые элементы для поддержки локализации в компонентах, таких как DataGrid и ResourcePage.
This commit is contained in:
Denozordec
2026-08-18 17:00:15 +07:00
parent e0d695f2a4
commit 653bc6cc91
43 changed files with 214 additions and 192 deletions
@@ -61,7 +61,7 @@ function DataGridColumnFilter<TData, TValue>({
<div className="hidden space-x-1 lg:flex">
{selectedValues.size > 2 ? (
<Badge variant="secondary" className="px-1 font-normal">
{selectedValues.size} selected
{selectedValues.size} выбрано
</Badge>
) : (
options
@@ -94,7 +94,7 @@ function DataGridColumnFilter<TData, TValue>({
<div className="max-h-[300px] overflow-y-auto">
{filteredOptions.length === 0 ? (
<div className="text-muted-foreground py-6 text-center text-sm">
No results found.
Ничего не найдено.
</div>
) : (
<div className="p-1">
@@ -170,7 +170,7 @@ function DataGridColumnFilter<TData, TValue>({
}}
className="hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground rounded-md relative flex cursor-pointer items-center justify-center px-2 py-1.5 text-sm outline-hidden select-none"
>
Clear filters
Сбросить фильтры
</div>
</div>
</>
@@ -39,11 +39,11 @@ function DataGridPagination(props: DataGridPaginationProps): React.JSX.Element {
sizes: [5, 10, 25, 50, 100],
sizesSkeleton: <Skeleton className="h-8 w-44" />,
moreLimit: 5,
info: "{from} - {to} of {count}",
info: "{from}{to} из {count}",
infoSkeleton: <Skeleton className="h-8 w-60" />,
rowsPerPageLabel: "Rows per page",
previousPageLabel: "Go to previous page",
nextPageLabel: "Go to next page",
rowsPerPageLabel: "Строк на странице",
previousPageLabel: "Предыдущая страница",
nextPageLabel: "Следующая страница",
ellipsisText: "...",
}
@@ -73,7 +73,7 @@ function DataGridTableDndRowHandle({ className }: { className?: string }) {
"size-7 cursor-grab opacity-70 hover:bg-transparent hover:opacity-100 active:cursor-grabbing",
className
)}
aria-label="Drag to reorder row"
aria-label="Перетащить строку"
disabled
>
<GripHorizontalIcon aria-hidden="true" />
@@ -89,7 +89,7 @@ function DataGridTableDndRowHandle({ className }: { className?: string }) {
"size-7 cursor-grab opacity-70 hover:bg-transparent hover:opacity-100 active:cursor-grabbing",
className
)}
aria-label="Drag to reorder row"
aria-label="Перетащить строку"
{...context.attributes}
{...context.listeners}
>
@@ -105,7 +105,7 @@ function DataGridTableDndHeader<TData>({
className={`-ms-2 size-6 ${isDragging ? "cursor-grabbing" : "cursor-grab active:cursor-grabbing"}`}
{...attributes}
{...listeners}
aria-label="Drag to reorder"
aria-label="Перетащить для изменения порядка"
>
<GripVerticalIcon className="opacity-60 hover:opacity-100" aria-hidden="true" />
</Button>
@@ -397,9 +397,9 @@ function DataGridTableVirtual<TData>({
const isVirtualizationEnabled = virtualizerOptions?.enabled !== false
const loadingMoreMessage =
props.fetchingMoreMessage || props.loadingMessage || "Loading..."
props.fetchingMoreMessage || props.loadingMessage || "Загрузка…"
const allRowsLoadedMessage =
props.allRowsLoadedMessage || "All records loaded"
props.allRowsLoadedMessage || "Все записи загружены"
const handleViewportRef = useCallback((node: HTMLDivElement | null) => {
setViewportElements({
@@ -1241,7 +1241,7 @@ function DataGridTableEmpty() {
colSpan={Math.max(visibleColumnCount, 1)}
className="text-muted-foreground py-6 text-center text-sm"
>
{props.emptyMessage || "No data available"}
{props.emptyMessage || "Нет данных"}
</td>
</tr>
)
@@ -1254,7 +1254,7 @@ function DataGridTableLoader() {
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">
<div className="text-muted-foreground bg-card rounded-lg flex items-center gap-2 border px-4 py-2 text-sm leading-none font-medium">
<Spinner className="size-5 opacity-60" />
{props.loadingMessage || "Loading..."}
{props.loadingMessage || "Загрузка…"}
</div>
</div>
)
@@ -1266,7 +1266,7 @@ function DataGridTableRowPin<TData>({ row }: { row: Row<TData> }) {
return (
<button
type="button"
aria-label={isPinned ? "Unpin row" : "Pin row"}
aria-label={isPinned ? "Открепить строку" : "Закрепить строку"}
onClick={() => {
if (isPinned) {
row.pin(false)
@@ -1322,7 +1322,7 @@ function DataGridTableRowSelect<TData>({ row }: { row: Row<TData> }) {
<Checkbox
checked={row.getIsSelected()}
onCheckedChange={(value) => row.toggleSelected(!!value)}
aria-label="Select row"
aria-label="Выбрать строку"
className="align-[inherit]"
/>
</>
@@ -1341,7 +1341,7 @@ function DataGridTableRowSelectAll() {
indeterminate={isSomeSelected && !isAllSelected}
disabled={isLoading || recordCount === 0}
onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
aria-label="Select all"
aria-label="Выбрать все"
className="align-[inherit]"
/>
)
@@ -1408,7 +1408,7 @@ function DataGridTableBodyRows<TData>({ table }: { table: Table<TData> }) {
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
{props.loadingMessage || "Loading..."}
{props.loadingMessage || "Загрузка…"}
</div>
</td>
</tr>
+49 -54
View File
@@ -123,75 +123,70 @@ export interface FilterI18nConfig {
// Default English i18n configuration
export const DEFAULT_I18N: FilterI18nConfig = {
// UI Labels
addFilter: "Filter",
searchFields: "Filter...",
noFieldsFound: "No filters found.",
noResultsFound: "No results found.",
select: "Select...",
true: "True",
false: "False",
min: "Min",
max: "Max",
to: "to",
typeAndPressEnter: "Type and press Enter to add tag",
selected: "selected",
selectedCount: "selected",
addFilter: "Фильтр",
searchFields: "Фильтр…",
noFieldsFound: "Поля не найдены.",
noResultsFound: "Ничего не найдено.",
select: "Выбрать…",
true: "Да",
false: "Нет",
min: "Мин.",
max: "Макс.",
to: "",
typeAndPressEnter: "Введите и нажмите Enter",
selected: "выбрано",
selectedCount: "выбрано",
percent: "%",
defaultCurrency: "$",
defaultColor: "#000000",
addFilterTitle: "Add filter",
addFilterTitle: "Добавить фильтр",
// Operators
operators: {
is: "is",
isNot: "is not",
isAnyOf: "is any of",
isNotAnyOf: "is not any of",
includesAll: "includes all",
excludesAll: "excludes all",
before: "before",
after: "after",
between: "between",
notBetween: "not between",
contains: "contains",
notContains: "does not contain",
startsWith: "starts with",
endsWith: "ends with",
isExactly: "is exactly",
equals: "equals",
notEquals: "not equals",
greaterThan: "greater than",
lessThan: "less than",
overlaps: "overlaps",
includes: "includes",
excludes: "excludes",
includesAllOf: "includes all of",
includesAnyOf: "includes any of",
empty: "is empty",
notEmpty: "is not empty",
is: "равно",
isNot: "не равно",
isAnyOf: "любое из",
isNotAnyOf: "кроме",
includesAll: "включает все",
excludesAll: "исключает все",
before: "до",
after: "после",
between: "между",
notBetween: "вне диапазона",
contains: "содержит",
notContains: "не содержит",
startsWith: "начинается с",
endsWith: "заканчивается на",
isExactly: "точно",
equals: "равно",
notEquals: "не равно",
greaterThan: "больше",
lessThan: "меньше",
overlaps: "пересекается",
includes: "включает",
excludes: "исключает",
includesAllOf: "включает все",
includesAnyOf: "включает любое",
empty: "пусто",
notEmpty: "не пусто",
},
// Placeholders
placeholders: {
enterField: (fieldType: string) => `Enter ${fieldType}...`,
selectField: "Select...",
searchField: (fieldName: string) => `Search ${fieldName.toLowerCase()}...`,
enterKey: "Enter key...",
enterValue: "Enter value...",
enterField: (fieldType: string) => `Введите ${fieldType}`,
selectField: "Выбрать…",
searchField: (fieldName: string) => `Поиск ${fieldName.toLowerCase()}`,
enterKey: "Введите ключ…",
enterValue: "Введите значение…",
},
// Helper functions
helpers: {
formatOperator: (operator: string) => operator.replace(/_/g, " "),
},
// Validation
validation: {
invalidEmail: "Invalid email format",
invalidUrl: "Invalid URL format",
invalidTel: "Invalid phone format",
invalid: "Invalid input format",
invalidEmail: "Некорректный email",
invalidUrl: "Некорректный URL",
invalidTel: "Некорректный телефон",
invalid: "Некорректное значение",
},
}