@object-ui/i18n 17.2.0 → 17.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +1817 -1
  2. package/README.md +26 -13
  3. package/dist/index.d.ts +3 -1
  4. package/dist/index.js +14 -1
  5. package/dist/locales/ar.d.ts +550 -107
  6. package/dist/locales/ar.js +646 -156
  7. package/dist/locales/de.d.ts +550 -107
  8. package/dist/locales/de.js +661 -178
  9. package/dist/locales/en.d.ts +586 -143
  10. package/dist/locales/en.js +851 -143
  11. package/dist/locales/es.d.ts +550 -107
  12. package/dist/locales/es.js +647 -160
  13. package/dist/locales/fr.d.ts +550 -107
  14. package/dist/locales/fr.js +640 -155
  15. package/dist/locales/index.d.ts +5587 -1157
  16. package/dist/locales/ja.d.ts +550 -107
  17. package/dist/locales/ja.js +632 -149
  18. package/dist/locales/ko.d.ts +550 -107
  19. package/dist/locales/ko.js +638 -156
  20. package/dist/locales/pt.d.ts +550 -107
  21. package/dist/locales/pt.js +639 -157
  22. package/dist/locales/ru.d.ts +550 -107
  23. package/dist/locales/ru.js +650 -156
  24. package/dist/locales/zh.d.ts +588 -145
  25. package/dist/locales/zh.js +629 -145
  26. package/dist/pickLocalized.d.ts +21 -0
  27. package/dist/pickLocalized.js +40 -7
  28. package/dist/provider.d.ts +125 -1
  29. package/dist/provider.js +380 -4
  30. package/dist/useDisplayLocale.d.ts +49 -0
  31. package/dist/useDisplayLocale.js +55 -0
  32. package/dist/useObjectLabel.d.ts +8 -2
  33. package/dist/useObjectLabel.js +28 -8
  34. package/dist/useSafeTranslation.js +67 -3
  35. package/dist/utils/index.d.ts +1 -0
  36. package/dist/utils/index.js +1 -0
  37. package/dist/utils/number-display.d.ts +32 -0
  38. package/dist/utils/number-display.js +32 -0
  39. package/dist/utils/spec-formatters.d.ts +39 -13
  40. package/dist/utils/spec-formatters.js +3 -3
  41. package/package.json +5 -4
@@ -1,4 +1,18 @@
1
1
  const ru = {
2
+ // objectui#4467 — the impersonation banner (app-shell ImpersonationBanner).
3
+ // Raised by `session.impersonatedBy`, so it survives SPA reboots; it names
4
+ // BOTH parties because the audit trail attributes the work to the impersonated
5
+ // user, and the exit states its own failure rather than appearing to succeed.
6
+ impersonation: {
7
+ banner: {
8
+ message: 'Вы работаете от имени {{user}} — все действия записываются на этого пользователя.',
9
+ startedBy: 'Начато администратором {{admin}}.',
10
+ stop: 'Прекратить работу от чужого имени',
11
+ stopping: 'Завершение…',
12
+ stopFailed: 'Не удалось прекратить работу от чужого имени: {{reason}}',
13
+ notRestored: 'Сервер принял запрос, но не восстановил сеанс администратора — вы всё ещё работаете от имени {{user}}. Выйдите и войдите снова, чтобы завершить.',
14
+ },
15
+ },
2
16
  // objectui#2600 B5 — capability picker scope group headers (labels come from the sys_capability registry).
3
17
  capability: {
4
18
  label: {
@@ -16,6 +30,32 @@ const ru = {
16
30
  other: 'Другое',
17
31
  },
18
32
  },
33
+ // objectui#3546 slice six — сводка шести граней авторизации в
34
+ // PermissionFacetLink (только чтение) плюс ссылка в Studio.
35
+ //
36
+ // Четыре счётных значения записаны как «Существительное: {{count}}» — этот
37
+ // приём в паке уже применён 25 раз (lookup.recordCount, notifications.
38
+ // groupCount, approvalsInbox.bulkApproved …) и он верен при ЛЮБОМ числе, так
39
+ // что для категорий few/many, которых в паке нет, базовый ключ даёт
40
+ // правильный русский, а не английский. Поэтому `_one` здесь совпадает с
41
+ // базовым ключом — форма не зависит от числа.
42
+ perm: {
43
+ facet: {
44
+ none: "Нет",
45
+ more: "+{{count}} ещё",
46
+ objects: "Объектов: {{count}}",
47
+ objects_one: "Объектов: {{count}}",
48
+ fields: "Правил для полей: {{count}}",
49
+ fields_one: "Правил для полей: {{count}}",
50
+ rls: "Политик RLS: {{count}}",
51
+ rls_one: "Политик RLS: {{count}}",
52
+ tabs: "Правил для вкладок: {{count}}",
53
+ tabs_one: "Правил для вкладок: {{count}}",
54
+ adminScope: "Делегированное администрирование настроено",
55
+ designInStudio: "Дизайн в Studio →",
56
+ designInStudioHint: "Дизайн в Studio",
57
+ },
58
+ },
19
59
  lookup: {
20
60
  recentlyUsed: 'Недавние',
21
61
  allResults: 'Все результаты',
@@ -46,13 +86,12 @@ const ru = {
46
86
  common: {
47
87
  addToFavorites: "Добавить в избранное",
48
88
  removeFromFavorites: "Удалить из избранного",
49
- loading: "Загрузка...",
89
+ loading: "Загрузка…",
50
90
  save: "Сохранить",
51
91
  cancel: "Отмена",
52
92
  delete: "Удалить",
53
93
  edit: "Редактировать",
54
94
  create: "Создать",
55
- search: "Поиск",
56
95
  filter: "Фильтр",
57
96
  reset: "Сбросить",
58
97
  confirm: "Подтвердить",
@@ -76,11 +115,20 @@ const ru = {
76
115
  required: "Обязательно",
77
116
  optional: "Необязательно",
78
117
  selectOption: "Выберите вариант",
79
- select: "Выбрать...",
118
+ select: "Выбрать…",
80
119
  openChat: "Открыть чат",
81
120
  closeChat: "Закрыть чат",
121
+ closePanel: "Закрыть панель",
122
+ resizeDrawer: "Изменить ширину панели",
123
+ itemCount: "{{count}} элементов",
124
+ itemCountOne: "{{count}} элемент",
82
125
  toggleSidebar: "Переключить боковую панель",
83
126
  package: "Пакет",
127
+ done: "Готово",
128
+ editInStudio: "Редактировать в Studio",
129
+ record: "Запись",
130
+ retry: "Повторить",
131
+ printDialogHint: "Открывает диалог печати браузера (это не экспорт в PDF)",
84
132
  },
85
133
  actions: {
86
134
  decisionOutput: {
@@ -103,6 +151,7 @@ const ru = {
103
151
  url: "Пожалуйста, введите корректный URL",
104
152
  pattern: "Неверный формат поля {{field}}",
105
153
  formInvalid: "Проверьте выделенные поля: {{fields}}",
154
+ formInvalidJoiner: ", ",
106
155
  unique: "{{field}} должно быть уникальным",
107
156
  type: "{{field}} должно быть допустимым {{type}}",
108
157
  },
@@ -111,6 +160,9 @@ const ru = {
111
160
  submitFailed: "Не удалось сохранить. Попробуйте ещё раз.",
112
161
  discardTitle: "Отменить изменения?",
113
162
  discardMessage: "Есть несохранённые изменения. Если закрыть форму сейчас, правки будут потеряны.",
163
+ // objectui#4024 — the create/edit dialog's `sr-only` accessible
164
+ // description, used when the form declares no `description` of its own.
165
+ dialogDescriptionFallback: "Заполните поля формы, затем отправьте или отмените.",
114
166
  keepEditing: "Продолжить редактирование",
115
167
  discard: "Отменить",
116
168
  conflictTitle: "Конфликт сохранения",
@@ -127,12 +179,21 @@ const ru = {
127
179
  stepOf: "Шаг {{current}} из {{total}}",
128
180
  createTitle: "Создать {{object}}",
129
181
  editTitle: "Редактировать {{object}}",
182
+ viewTitle: "Просмотреть {{object}}",
183
+ createTargetOrg: "Создаётся в {{org}}",
130
184
  saveRecord: "Сохранить запись",
131
185
  create: "Создать",
132
186
  update: "Обновить",
133
187
  createSuccess: "{{object}} создан",
134
188
  updateSuccess: "{{object}} обновлён",
135
189
  deleteSuccess: "{{object}} удалён",
190
+ fullscreen: {
191
+ title: "Изменить текст",
192
+ description: "Измените полное текстовое значение, затем сохраните или отмените изменения.",
193
+ done: "Готово",
194
+ toggle: "Редактировать {{label}} в полноэкранном режиме",
195
+ textFallback: "текст",
196
+ },
136
197
  },
137
198
  fields: {
138
199
  image: {
@@ -170,7 +231,11 @@ const ru = {
170
231
  richText: {
171
232
  format: "Формат: {{format}}",
172
233
  basicEditorHint: "Редактор форматированного текста (базовый)",
173
- placeholder: "Введите текст...",
234
+ placeholder: "Введите текст…",
235
+ },
236
+ options: {
237
+ empty: "Нет доступных вариантов",
238
+ selectFirst: "Сначала выберите {{fields}}",
174
239
  },
175
240
  objectRef: {
176
241
  loading: "Загрузка объектов…",
@@ -199,6 +264,13 @@ const ru = {
199
264
  editAsJson: "Редактировать как JSON",
200
265
  useVisualBuilder: "Использовать визуальный конструктор",
201
266
  },
267
+ tags: {
268
+ placeholder: "Введите и нажмите Enter, чтобы добавить…",
269
+ },
270
+ textarea: {
271
+ characterCount: "Количество символов: {{count}} из {{max}}",
272
+ charactersRemaining: "Осталось символов: {{count}}",
273
+ },
202
274
  },
203
275
  table: {
204
276
  rowsPerPage: "Строк на странице",
@@ -225,7 +297,7 @@ const ru = {
225
297
  saveAll: "Сохранить всё ({{count}})",
226
298
  addRecord: "Добавить запись",
227
299
  open: "Открыть",
228
- search: "Поиск...",
300
+ search: "Поиск…",
229
301
  modified: "{{count}} строк изменено",
230
302
  saveFailed: 'Не удалось сохранить',
231
303
  selected: "{{count}} выбрано",
@@ -269,7 +341,7 @@ const ru = {
269
341
  delete: "Удалить",
270
342
  export: "Экспорт",
271
343
  exportAs: "Экспорт в {{format}}",
272
- loading: "Загрузка таблицы...",
344
+ loading: "Загрузка таблицы…",
273
345
  errorLoading: "Ошибка загрузки таблицы",
274
346
  pullToRefresh: "Потяните для обновления",
275
347
  refreshing: "Обновление…",
@@ -280,6 +352,22 @@ const ru = {
280
352
  yes: "Да",
281
353
  no: "Нет",
282
354
  systemFields: "Система",
355
+ // objectui#4024 — column-footer aggregate prefixes, keyed by the spec's
356
+ // `ColumnSummary` vocabulary. `pattern` owns the label/value join so this
357
+ // pack controls its own separator and word order.
358
+ summary: {
359
+ pattern: "{{label}}: {{value}}",
360
+ count: "Количество",
361
+ countEmpty: "Пустые",
362
+ countFilled: "Заполненные",
363
+ countUnique: "Уникальные",
364
+ percentEmpty: "Пустые",
365
+ percentFilled: "Заполненные",
366
+ sum: "Сумма",
367
+ avg: "Среднее",
368
+ min: "Мин.",
369
+ max: "Макс.",
370
+ },
283
371
  toolbar: {
284
372
  densityMode: "Плотность",
285
373
  densityCompact: "Компактный",
@@ -393,12 +481,12 @@ const ru = {
393
481
  templateName: "Название шаблона",
394
482
  save: "Сохранить",
395
483
  deleteTemplate: "Удалить шаблон",
396
- savedMapping: 'Saved mapping:',
397
- chooseSavedMapping: 'Choose a saved mapping…',
398
- manualMapping: '— Map columns manually —',
399
- transform: 'Transform',
400
- savedMappingHint: 'Mapping “{{name}}” applies rename + transforms + type coercion on the server. Column mapping is read-only.',
401
- savedMappingPreviewNote: 'The preview shows your source columns; on import, mapping “{{name}}” applies rename, transforms and type coercion on the server.',
484
+ savedMapping: 'Сохранённое сопоставление:',
485
+ chooseSavedMapping: 'Выбрать сохранённое сопоставление…',
486
+ manualMapping: '— Сопоставить столбцы вручную —',
487
+ transform: 'Преобразование',
488
+ savedMappingHint: 'Сопоставление «{{name}}» применяет на сервере переименование + преобразования + приведение типов. Сопоставление столбцов доступно только для чтения.',
489
+ savedMappingPreviewNote: 'В предпросмотре показаны исходные столбцы; при импорте сопоставление «{{name}}» применяет на сервере переименование, преобразования и приведение типов.',
402
490
  csvColumn: "Столбец",
403
491
  mapsTo: "Сопоставляется с",
404
492
  typeMismatch: "Похоже на {{type}}",
@@ -458,6 +546,8 @@ const ru = {
458
546
  loadErrorUnauthorizedMessage: "Сессия истекла или вы вышли из системы. Войдите снова, чтобы просмотреть эти записи.",
459
547
  loadErrorRejectedTitle: "Запрос этого представления отклонён",
460
548
  loadErrorRejectedMessage: "Сервер не смог обработать фильтр или параметры запроса этого представления. Обычно помогает сброс фильтров; если представление сохранено в таком виде, исправить его должен администратор.",
549
+ loadErrorApiDisabledTitle: "Этот объект недоступен через API",
550
+ loadErrorApiDisabledMessage: "Страница не может загрузить записи, потому что объект не открыт через API. Это настройка самого объекта, а не права доступа — администратор должен включить доступ по API, чтобы эта страница заработала.",
461
551
  retry: "Повторить",
462
552
  managedBy: {
463
553
  system: {
@@ -482,7 +572,7 @@ const ru = {
482
572
  },
483
573
  },
484
574
  refresh: "Обновить",
485
- loading: 'Loading records...',
575
+ loading: "Загрузка записей…",
486
576
  recordCount: "{{count}} записей",
487
577
  recordCountOne: "{{count}} запись",
488
578
  addRecord: "Добавить запись",
@@ -494,7 +584,8 @@ const ru = {
494
584
  sort: "Сортировка",
495
585
  sortRecords: "Сортировка записей",
496
586
  sortByIdSuffix: "(по ID)",
497
- sortRelationalHint: "Столбцы, ссылающиеся на другую запись, здесь не показаны: их можно сортировать только по сохранённому ID, а не по имени, которое видно в ячейке. Чтобы сортировать по этому имени, добавьте поле-формулу с ним.",
587
+ sortRelationalHint: "Столбцы, ссылающиеся на другую запись, здесь не показаны: их можно сортировать только по сохранённому ID, а не по имени, которое видно в ячейке. Чтобы сортировать по этому имени, денормализуйте его в этот объект — как сохраняемое поле, которое записывается при изменении источника, — и сортируйте по нему. Не поле-формула: она виртуальна, столбец для неё не хранится, и сервер отказывается сортировать по ней.",
588
+ resetSortToDefault: "Сбросить к сортировке представления",
498
589
  group: "Группировка",
499
590
  groupBy: "Группировать по",
500
591
  export: "Экспорт",
@@ -552,13 +643,16 @@ const ru = {
552
643
  },
553
644
  kanban: {
554
645
  uncategorized: "Без категории",
646
+ columns: "колонок",
555
647
  addCard: "Добавить карточку",
556
648
  addColumn: "Добавить колонку",
557
649
  moveCard: "Переместить карточку",
558
650
  deleteCard: "Удалить карточку",
559
651
  deleteColumn: "Удалить колонку",
560
652
  noCards: "Нет карточек",
561
- cardTitlePlaceholder: "Введите название карточки...",
653
+ cardTitlePlaceholder: "Введите название карточки…",
654
+ requiredFieldsTitle: "Заполните обязательные поля",
655
+ requiredFieldsDescription: "Это перемещение делает поля ниже обязательными. Заполните их, чтобы продолжить.",
562
656
  },
563
657
  timeline: {
564
658
  bucket: {
@@ -571,6 +665,13 @@ const ru = {
571
665
  noDate: "Без даты",
572
666
  unassigned: "Не назначено",
573
667
  },
668
+ scale: {
669
+ week: "Неделя {{n}}",
670
+ quarter: "{{quarter}} кв. {{year}}",
671
+ },
672
+ gantt: {
673
+ rowLabel: "Элементы",
674
+ },
574
675
  },
575
676
  gantt: {
576
677
  viewMode: {
@@ -617,6 +718,18 @@ const ru = {
617
718
  ff: "Окончание → Окончание",
618
719
  sf: "Начало → Окончание",
619
720
  },
721
+ linkEnd: {
722
+ start: "Начало",
723
+ end: "Конец",
724
+ },
725
+ link: {
726
+ rejected: {
727
+ self: "Задача не может зависеть от самой себя.",
728
+ locked: "Эта строка заблокирована и не может принять новую зависимость.",
729
+ group: "Сводная строка не может быть целью зависимости — свяжите одну из её задач.",
730
+ cycle: "Эта связь создаст циклическую зависимость.",
731
+ },
732
+ },
620
733
  conflict: {
621
734
  title: "Конфликт расписания",
622
735
  body: "Это перемещение противоречит ограничениям зависимостей. Автоматически перепланировать затронутые задачи ({{count}})?",
@@ -625,8 +738,8 @@ const ru = {
625
738
  },
626
739
  autoScheduleDlg: {
627
740
  title: "Автопланирование",
628
- body: "Сдвинуть {count} задач(и) на более поздний срок, чтобы соблюсти связи зависимостей?",
629
- skipped: "{count} заблокированных задач(и) также нарушают связи и были пропущены.",
741
+ body: "Сдвинуть {{count}} задач(и) на более поздний срок, чтобы соблюсти связи зависимостей?",
742
+ skipped: "{{count}} заблокированных задач(и) также нарушают связи и были пропущены.",
630
743
  confirm: "Применить",
631
744
  cancel: "Отмена",
632
745
  none: "Все зависимости соблюдены — перепланировать нечего.",
@@ -637,6 +750,12 @@ const ru = {
637
750
  over: "перегружен",
638
751
  empty: "Нет задач для распределения.",
639
752
  },
753
+ quickFilter: {
754
+ all: "Все",
755
+ clear: "Очистить фильтры",
756
+ empty: "Нет вариантов",
757
+ resultSummary: "Показано {shown} / {total} задач",
758
+ },
640
759
  readOnly: "Только чтение",
641
760
  readOnlyHint: "Редактирование в этом представлении отключено.",
642
761
  lockedHint: "Нет прав на редактирование",
@@ -657,6 +776,7 @@ const ru = {
657
776
  exportPng: "Экспортировать в PNG",
658
777
  exportPdf: "Экспортировать в PDF",
659
778
  saveLayout: "Сохранить компоновку",
779
+ refresh: "Обновить",
660
780
  undo: "Отменить",
661
781
  redo: "Повторить",
662
782
  prevPeriod: "Предыдущий период",
@@ -697,11 +817,11 @@ const ru = {
697
817
  defaultBadge: "по умолчанию",
698
818
  tabActionsFor: "Действия с представлением {{name}}",
699
819
  readonlyAriaLabel: "Представление только для чтения",
700
- readonlyTooltip: "Системное представление — скопируйте для настройки.",
820
+ readonlyTooltip: "Системное представление — определено в коде, только для чтения.",
701
821
  },
702
822
  designer: {
703
- undo: 'Undo',
704
- redo: 'Redo',
823
+ undo: "Отменить",
824
+ redo: "Повторить",
705
825
  },
706
826
  detail: {
707
827
  editInlineHint: "Дважды щёлкните для редактирования",
@@ -721,6 +841,15 @@ const ru = {
721
841
  viewHistory: "Просмотр истории",
722
842
  delete: "Удалить",
723
843
  moreActions: "Другие действия",
844
+ addReaction: "Добавить реакцию",
845
+ pageHeaderActions: "Действия в заголовке страницы",
846
+ emojiPicker: "Выбор эмодзи",
847
+ reactionCount: "{{emoji}} {{count}} реакций",
848
+ reactionCountOne: "{{emoji}} {{count}} реакция",
849
+ recordDetail: "Сведения о записи",
850
+ recordDetailWithLabel: "Сведения: {{label}}",
851
+ openAsFullPage: "Открыть на всю страницу",
852
+ recordDetailOverlay: "Наложение со сведениями о записи для {{title}}.",
724
853
  addToFavorites: "Добавить в избранное",
725
854
  removeFromFavorites: "Удалить из избранного",
726
855
  previousRecord: "Предыдущая запись",
@@ -734,13 +863,15 @@ const ru = {
734
863
  relatedRecords: "{{count}} записей",
735
864
  relatedRecordOne: "{{count}} запись",
736
865
  noRelatedRecords: "Связанные записи не найдены",
737
- loading: "Загрузка...",
866
+ loading: "Загрузка…",
738
867
  copyToClipboard: "Копировать в буфер обмена",
739
868
  copied: "Скопировано!",
740
869
  deleteConfirmation: "Вы уверены, что хотите удалить эту запись?",
870
+ deleted: "Запись удалена",
741
871
  editRecord: "Редактировать запись",
742
872
  viewAll: "Показать все",
743
873
  new: "Создать",
874
+ add: "Добавить",
744
875
  emptyValue: "—",
745
876
  activity: "Активность",
746
877
  editRow: "Редактировать",
@@ -751,7 +882,7 @@ const ru = {
751
882
  nextPage: "Далее",
752
883
  pageOf: "Страница {{current}} из {{total}}",
753
884
  sortBy: "Сортировать по",
754
- filterPlaceholder: "Фильтр...",
885
+ filterPlaceholder: "Фильтр…",
755
886
  highlightFields: "Ключевые поля",
756
887
  comments: "Комментарии",
757
888
  searchComments: "Поиск комментариев…",
@@ -816,6 +947,7 @@ const ru = {
816
947
  loadMore: "Загрузить ещё",
817
948
  edited: "(изменено)",
818
949
  via: "через {{source}}",
950
+ viewSource: "Показать источник",
819
951
  replyCount: "{{count}} ответ",
820
952
  replyCountPlural: "{{count}} ответов",
821
953
  replyPlaceholder: "Ответить…",
@@ -828,14 +960,15 @@ const ru = {
828
960
  saving: "Сохранение…",
829
961
  lockedByApproval: "Заблокировано для согласования",
830
962
  lockedTooltip: "У этой записи есть ожидающий запрос на согласование; редактирование заблокировано",
831
- writeStrippedTitle: "Часть полей не сохранена",
832
- writeStrippedReadonly: "Поля только для чтения, поэтому не сохранены: {{fields}}",
833
- writeStrippedByState: "Поля недоступны для редактирования в текущем состоянии записи, поэтому не сохранены: {{fields}}",
963
+ writeStrippedTitle: "Сохранено, но часть полей не применена",
964
+ writeStrippedReadonly: "Поля только для чтения, поэтому не применены: {{fields}}",
965
+ writeStrippedByState: "Поля недоступны для редактирования в текущем состоянии записи, поэтому не применены: {{fields}}",
834
966
  approvalPendingEditable: "На согласовании · редактирование доступно",
835
967
  approvalPendingTooltip: "У этой записи есть ожидающий запрос на согласование, но этот шаг всё ещё разрешает редактирование",
836
968
  approvalProgress: "Согласования — {{got}} из {{need}}",
837
969
  approvalProgressGroups: "Подписи — {{got}} из {{need}} групп",
838
970
  approvalProgressLabel: "Ход согласования",
971
+ approvalsPanelTitle: "Согласования",
839
972
  cancelApproval: "Отменить согласование",
840
973
  cancelApprovalInFlight: "Отмена…",
841
974
  cancelApprovalTooltip: "Отмените ожидающий запрос на согласование, чтобы разблокировать запись",
@@ -856,11 +989,20 @@ const ru = {
856
989
  concurrentUpdateReload: "Загрузить текущую версию",
857
990
  concurrentUpdateOverwrite: "Всё равно перезаписать",
858
991
  concurrentUpdateCancel: "Отмена",
992
+ concurrentUpdateRecordLabel: "этой записи",
859
993
  openInNewTab: "Открыть в новой вкладке",
860
994
  history: "История",
995
+ historyEmpty: "Истории пока нет",
861
996
  deleteRowTitle: "Удалить запись",
862
997
  createdBy: "Создано",
863
998
  updatedBy: "Обновлено",
999
+ // objectui#3863 — base key, and in ru this is the slot users actually hit: `few`
1000
+ // (2-4) and `many` (5-20, 25-30, …) are unenumerated, so before this key those
1001
+ // counts rendered ENGLISH. The value therefore cannot agree with the numeral —
1002
+ // it uses the «Существительное: {{count}}» form this pack already writes 22 times
1003
+ // (lookup.recordCount `Записей: {{count}}`, notifications.groupCount), which is
1004
+ // correct for EVERY Russian count. `_one` keeps the agreeing form for 1/21/31/…
1005
+ showEmptyRelated: "+ Пустых: {{count}}",
864
1006
  showEmptyRelated_one: "+ {{count}} пустое",
865
1007
  showEmptyRelated_other: "+ {{count}} пустых",
866
1008
  copyEmail: "Копировать email",
@@ -872,7 +1014,8 @@ const ru = {
872
1014
  },
873
1015
  chart: {
874
1016
  noData: "Нет данных для графика",
875
- loading: "Загрузка графика...",
1017
+ loading: "Загрузка графика…",
1018
+ nullCategory: "(Не указано)",
876
1019
  },
877
1020
  map: {
878
1021
  searchLocations: "Поиск местоположений…",
@@ -894,8 +1037,8 @@ const ru = {
894
1037
  properties: "Свойства",
895
1038
  connections: "Соединения",
896
1039
  quickConnect: "Быстрое соединение",
897
- fromPlaceholder: "От...",
898
- toPlaceholder: "К...",
1040
+ fromPlaceholder: "От…",
1041
+ toPlaceholder: "К…",
899
1042
  connect: "Соединить",
900
1043
  label: "Метка",
901
1044
  type: "Тип",
@@ -943,6 +1086,7 @@ const ru = {
943
1086
  },
944
1087
  dashboard: {
945
1088
  noRows: "Нет строк",
1089
+ loading: "Загрузка…",
946
1090
  pickMeasures: "Выберите меры (значения) для этого виджета набора данных.",
947
1091
  datasetUnsupported: "Этот источник данных не поддерживает запросы к наборам данных.",
948
1092
  details: "Подробности",
@@ -1036,7 +1180,7 @@ const ru = {
1036
1180
  faviconUrl: "Favicon URL",
1037
1181
  preview: "Предпросмотр",
1038
1182
  complete: "Завершить",
1039
- snakeCaseHint: "Must be snake_case (e.g. my_app)",
1183
+ snakeCaseHint: "Должно быть в формате snake_case (например, my_app)",
1040
1184
  modeEdit: "Редактировать",
1041
1185
  modePreview: "Предпросмотр",
1042
1186
  modeCode: "Код",
@@ -1200,6 +1344,7 @@ const ru = {
1200
1344
  },
1201
1345
  },
1202
1346
  console: {
1347
+ saveAdvisoryTitle: "Сохранено — проверка авторинга выдала рекомендаций: {{count}}",
1203
1348
  settingsHub: {
1204
1349
  title: "Настройки",
1205
1350
  subtitle: "Настройте рабочее пространство, интеграции и флаги функций.",
@@ -1266,7 +1411,7 @@ const ru = {
1266
1411
  shareTitle: "Поделиться этим диалогом",
1267
1412
  shareDisabledTitle: "Начните диалог, чтобы включить публикацию",
1268
1413
  newChat: "Создать",
1269
- searchChats: "Поиск по чатам...",
1414
+ searchChats: "Поиск по чатам…",
1270
1415
  noChatsYet: "Чатов пока нет",
1271
1416
  noChatsDescription: "Начните новый диалог, и он появится здесь.",
1272
1417
  noMatchingChats: "Подходящих чатов нет.",
@@ -1275,18 +1420,18 @@ const ru = {
1275
1420
  deleteConversation: "Удалить диалог",
1276
1421
  saveRename: "Сохранить название",
1277
1422
  cancelRename: "Отменить переименование",
1278
- loadingHistory: "Загрузка истории диалога...",
1423
+ loadingHistory: "Загрузка истории диалога…",
1279
1424
  conversationReady: "Диалог готов",
1280
1425
  preparingConversation: "Подготовка нового диалога",
1281
1426
  offlineDemoMode: "Автономный демонстрационный режим — список агентов недоступен",
1282
1427
  sendFailedRateLimited: "Вы отправляете сообщения слишком часто. Ваше сообщение сохранено ниже — подождите немного и попробуйте снова.",
1283
1428
  sendFailedGeneric: "Не удалось отправить сообщение. Оно сохранено ниже — попробуйте ещё раз.",
1284
- askAgent: "Спросить {{agent}}...",
1429
+ askAgent: "Спросить {{agent}}…",
1285
1430
  assistant: "Ассистент",
1286
1431
  liveCanvas: "Живой предпросмотр — {{app}} (черновик)",
1287
1432
  liveCanvasUnlisted: "Работающее приложение — {{app}} (скрыто до публикации)",
1288
- loadingAgents: "Загрузка агентов...",
1289
- askAnything: "Спросите о чём угодно...",
1433
+ loadingAgents: "Загрузка агентов…",
1434
+ askAnything: "Спросите о чём угодно…",
1290
1435
  emptyTitle: "Начните диалог",
1291
1436
  emptyDescription: "Спросите о чём угодно — ассистент видит контекст вашего текущего приложения.",
1292
1437
  switchAssistant: "Сменить ассистента",
@@ -1389,9 +1534,60 @@ const ru = {
1389
1534
  createSeed: "Сгенерировать примеры данных",
1390
1535
  createPackage: "Создать пакет приложения",
1391
1536
  },
1537
+ // objectui#3546 slice four — the AI console surfaces: the /ai chat page's app switcher,
1538
+ // connection banner and plan/publish cards, the ChatDock chrome, and the
1539
+ // conversation-list date buckets. `group.*` is the template-key family
1540
+ // `console.ai.group.${key}` (ConversationsSidebar), enumerated from the
1541
+ // ConversationGroupKey union — all five members, no wildcard.
1542
+ collapseToDock: "Свернуть в боковую панель",
1543
+ switchApp: "Сменить приложение",
1544
+ switchAppLabel: "Диалоги сборки по приложениям",
1545
+ newApp: "Новое приложение",
1546
+ connectionWaiting: "Ожидание сервера…",
1547
+ connectionStalled: "Всё ещё выполняется…",
1548
+ connectionOffline: "Соединение потеряно — переподключение…",
1549
+ designingPlan: "Проектирование вашего приложения…",
1550
+ designingPlanHint: {
1551
+ data: "Определяю данные, которые вы будете отслеживать…",
1552
+ objects: "Формирую объекты и их поля…",
1553
+ relations: "Соединяю связанные записи…",
1554
+ lookups: "Настраиваю связи и подстановки…",
1555
+ views: "Планирую экраны и представления…",
1556
+ forms: "Размещаю формы и списки…",
1557
+ defaults: "Добавляю разумные значения по умолчанию и проверки…",
1558
+ dashboard: "Набрасываю дашборд для отслеживания…",
1559
+ review: "Перепроверяю, что структура согласована…",
1560
+ finalize: "Собираю план воедино…",
1561
+ },
1562
+ planBuilding: "Сборка…",
1563
+ planBuilt: "Собрано",
1564
+ planDeferred: "Ещё не собрано",
1565
+ planReady: "План готов. Соберите его сейчас или скажите, что нужно скорректировать.",
1566
+ published: "Опубликовано",
1567
+ publishFailed: "Не удалось опубликовать",
1568
+ unavailableTitle: "Ассистент ИИ недоступен",
1569
+ unavailableDescription: "В этой среде ассистент ИИ не включён. Всё остальное работает как обычно.",
1570
+ unavailableError: "Не удалось связаться с сервисом ИИ. Возможно, он временно недоступен — повторите попытку или вернитесь на главную.",
1571
+ unavailableRetry: "Повторить",
1572
+ unavailableHome: "На главную",
1573
+ dock: {
1574
+ title: "Ассистент",
1575
+ description: "Чат с ассистентом ИИ",
1576
+ resize: "Изменить размер чата",
1577
+ collapse: "Свернуть чат",
1578
+ maximize: "Открыть на всю страницу",
1579
+ open: "Открыть ассистента",
1580
+ },
1581
+ group: {
1582
+ today: "Сегодня",
1583
+ yesterday: "Вчера",
1584
+ previous7Days: "Предыдущие 7 дней",
1585
+ previous30Days: "Предыдущие 30 дней",
1586
+ older: "Ранее",
1587
+ },
1392
1588
  },
1393
1589
  title: "Консоль ObjectStack",
1394
- initializing: "Инициализация приложения...",
1590
+ initializing: "Инициализация приложения…",
1395
1591
  loadingHint: "Настройка нового окружения может занять некоторое время.",
1396
1592
  breadcrumb: {
1397
1593
  dashboards: "Панели",
@@ -1399,6 +1595,31 @@ const ru = {
1399
1595
  reports: "Отчёты",
1400
1596
  system: "Система",
1401
1597
  },
1598
+ // objectui#4024 — the single-namespace settings screen. Its sibling
1599
+ // `settingsHub` above already resolved through this pack; the view was the
1600
+ // one file still carrying English literals.
1601
+ settingsView: {
1602
+ backToHub: "Все настройки",
1603
+ back: "Назад",
1604
+ noNamespace: "Пространство имён не выбрано.",
1605
+ loadError: "Не удалось загрузить настройки",
1606
+ saved: "Настройки сохранены",
1607
+ saveFailed: "Ошибка сохранения",
1608
+ lockedByEnv: "Заблокировано окружением: {{key}}",
1609
+ lockedByEnvNoKey: "Заблокировано окружением",
1610
+ actionSucceeded: "Действие выполнено",
1611
+ actionFailed: "Действие не выполнено",
1612
+ discard: "Отменить",
1613
+ saveChanges: "Сохранить изменения",
1614
+ unsavedCount: "Несохранённых изменений: {{count}}",
1615
+ unsavedCount_one: "{{count}} несохранённое изменение",
1616
+ unsavedCount_other: "{{count}} несохранённых изменений",
1617
+ cryptoRefusalTitle: "Эта установка не может шифровать секреты",
1618
+ cryptoRefusalSubjectSuffix: "объявлен зашифрованным, поэтому ничего не было записано.",
1619
+ cryptoRefusalNoSubject: "Значение, объявленное зашифрованным, было отклонено, поэтому ничего не было записано.",
1620
+ cryptoRefusalToast: "Не удалось зашифровать секреты: {{subject}}",
1621
+ cryptoRefusalToastNoSubject: "Не удалось зашифровать секреты",
1622
+ },
1402
1623
  loadingSteps: {
1403
1624
  connecting: "Подключение к источнику данных",
1404
1625
  loadingConfig: "Загрузка конфигурации",
@@ -1414,6 +1635,13 @@ const ru = {
1414
1635
  retry: "Повторить",
1415
1636
  retrying: "Повтор…",
1416
1637
  },
1638
+ serverAction: {
1639
+ openingTitle: "Открытие…",
1640
+ openingBody: "Открытие… это может занять некоторое время.",
1641
+ popupBlockedTitle: "Всплывающее окно заблокировано",
1642
+ popupBlockedDescription: "Браузер заблокировал открытие новой вкладки.",
1643
+ popupBlockedAction: "Открыть в новой вкладке",
1644
+ },
1417
1645
  shortcuts: {
1418
1646
  title: "Горячие клавиши",
1419
1647
  description: "Краткий справочник по всем доступным горячим клавишам.",
@@ -1421,6 +1649,7 @@ const ru = {
1421
1649
  general: "Общие",
1422
1650
  navigation: "Навигация",
1423
1651
  dataViews: "Представления данных",
1652
+ aiChat: "Ассистент ИИ",
1424
1653
  preferences: "Настройки",
1425
1654
  },
1426
1655
  openCommandPalette: "Открыть палитру команд",
@@ -1431,11 +1660,13 @@ const ru = {
1431
1660
  createRecord: "Создать новую запись",
1432
1661
  refreshData: "Обновить данные",
1433
1662
  editRecord: "Редактировать выбранную запись",
1663
+ newChat: "Новый чат",
1664
+ toggleChatsList: "Переключить список чатов",
1434
1665
  toggleDarkMode: "Переключить тёмный режим",
1435
1666
  },
1436
1667
  commandPalette: {
1437
1668
  title: "Палитра команд",
1438
- placeholder: "Введите команду или поиск...",
1669
+ placeholder: "Введите команду или поиск…",
1439
1670
  noResults: "Результаты не найдены.",
1440
1671
  objects: "Объекты",
1441
1672
  dashboards: "Панели мониторинга",
@@ -1461,6 +1692,12 @@ const ru = {
1461
1692
  goHome: "На главную",
1462
1693
  errorDetails: "Подробности ошибки (только для разработки)",
1463
1694
  },
1695
+ // objectui#3546 slice four — the console's catch-all route (AppContent `RouteNotFound`).
1696
+ notFound: {
1697
+ title: "Страница не найдена",
1698
+ description: "Открытый URL не соответствует ни одному представлению в этом приложении.",
1699
+ back: "Назад",
1700
+ },
1464
1701
  theme: {
1465
1702
  toggle: "Переключить тему",
1466
1703
  light: "Светлая",
@@ -1476,11 +1713,15 @@ const ru = {
1476
1713
  viewNameHelp: "Машинный ключ (snake_case). Заполняется автоматически из заголовка — при желании измените.",
1477
1714
  viewNameRequired: "Введите ключ (строчные буквы, цифры, подчёркивание). Для нелатинских заголовков автозаполнение не работает.",
1478
1715
  viewNameInvalid: "Используйте строчные латинские буквы, цифры и подчёркивания; начните с буквы или подчёркивания.",
1479
- systemViewReadonly: 'System view defined in code - duplicate to customize.',
1480
- expandToPage: 'Open as full page',
1716
+ systemViewReadonly: "Системное представление определено в коде — только для чтения.",
1717
+ cannotEditMetaView: "Это встроенное представление, определённое в коде, — изменить его нельзя.",
1718
+ cannotDeleteMetaView: "Это встроенное представление, определённое в коде, — удалить его нельзя.",
1719
+ expandToPage: "Открыть на всю страницу",
1481
1720
  objectNotFound: "Объект не найден",
1482
1721
  objectNotFoundDescription: "Объект «{{objectName}}» не существует в текущей конфигурации.",
1483
1722
  objectNotFoundHint: "Проверьте настройки навигации приложения или выберите другой объект на боковой панели.",
1723
+ filterOrNotSavable: "Этот фильтр объединяет условия через ИЛИ, что сохранённое представление пока не может хранить. Он по-прежнему применяется к этому списку — уберите группировку ИЛИ, чтобы сохранить его в представлении.",
1724
+ filterNestedNotSavable: "Этот фильтр использует вложенные группы условий, которые сохранённое представление не может хранить. Преобразуйте его в один список условий, чтобы сохранить в представлении.",
1484
1725
  allRecords: "Все записи",
1485
1726
  exitDesignMode: "Выйти из режима дизайна",
1486
1727
  enterDesignMode: "Войти в режим дизайна",
@@ -1507,7 +1748,7 @@ const ru = {
1507
1748
  exportPrintHint: "Форматы экспорта, печать и отображение количества записей",
1508
1749
  showAllFields: "Показать все",
1509
1750
  hideAllFields: "Скрыть все",
1510
- searchFields: "Поиск полей...",
1751
+ searchFields: "Поиск полей…",
1511
1752
  title: "Заголовок",
1512
1753
  description: "Описание",
1513
1754
  data: "Данные",
@@ -1546,7 +1787,7 @@ const ru = {
1546
1787
  longitudeField: "Поле долготы",
1547
1788
  imageField: "Поле изображения",
1548
1789
  dateField: "Поле даты",
1549
- selectField: "Выберите поле...",
1790
+ selectField: "Выберите поле…",
1550
1791
  gridOptionsHint: "Представление таблицы использует столбцы, настроенные выше.",
1551
1792
  groupBy: "Группировать по",
1552
1793
  prefixField: "Поле префикса",
@@ -1609,7 +1850,7 @@ const ru = {
1609
1850
  latitudeFieldHelp: "Поле с широтой (только гео-поля).",
1610
1851
  longitudeFieldHelp: "Поле с долготой (только гео-поля).",
1611
1852
  imageFieldHelp: "Обложка галереи берётся из этого поля изображения или вложений.",
1612
- selectOption: "Выбрать...",
1853
+ selectOption: "Выбрать…",
1613
1854
  noEligibleFieldForType: "Нет подходящих полей этого типа. Сначала добавьте его к объекту.",
1614
1855
  viewTypeUnavailable: "У этого объекта нет поля, которое может служить \"{{field}}\".",
1615
1856
  viewTypeUnavailableShort: "Не поддерживается этим объектом.",
@@ -1659,7 +1900,7 @@ const ru = {
1659
1900
  ufDropdown: "Выпадающий список",
1660
1901
  ufTabs: "Вкладки",
1661
1902
  ufToggle: "Переключатель",
1662
- ufAddField: "+ Добавить поле фильтра...",
1903
+ ufAddField: "+ Добавить поле фильтра…",
1663
1904
  ufNoFields: "Поля недоступны",
1664
1905
  ufAddTab: "+ Добавить вкладку",
1665
1906
  ufTabLabel: "Метка",
@@ -1719,7 +1960,7 @@ const ru = {
1719
1960
  passwordPlaceholder: "Введите пароль",
1720
1961
  forgotPasswordText: "Забыли пароль?",
1721
1962
  submitButton: "Войти",
1722
- submittingButton: "Вход...",
1963
+ submittingButton: "Вход…",
1723
1964
  noAccountText: "Нет аккаунта?",
1724
1965
  signUpText: "Зарегистрироваться",
1725
1966
  errors: {
@@ -1727,6 +1968,18 @@ const ru = {
1727
1968
  invalidCredentials: "Неверный email или пароль. Попробуйте ещё раз.",
1728
1969
  emailNotVerified: "Пожалуйста, подтвердите email перед входом.",
1729
1970
  },
1971
+ // objectui#3546 slice three — phone/OTP sign-in. `{seconds}` is LoginForm's own
1972
+ // literal `.replace()` hole, not i18next interpolation: keep the single braces.
1973
+ emailOrPhoneLabel: "Электронная почта или номер телефона",
1974
+ emailOrPhonePlaceholder: "name@example.com или +1 555 000 0000",
1975
+ phoneLabel: "Номер телефона",
1976
+ phonePlaceholder: "+1 555 000 0000",
1977
+ otpCodeLabel: "Код подтверждения",
1978
+ otpCodePlaceholder: "6-значный код",
1979
+ sendOtpButton: "Получить код",
1980
+ resendOtpCountdownText: "Отправить снова через {seconds} с",
1981
+ usePhoneOtpText: "Войти по коду подтверждения",
1982
+ usePasswordSignInText: "Войти с паролем",
1730
1983
  },
1731
1984
  register: {
1732
1985
  title: "Создать аккаунт",
@@ -1742,7 +1995,7 @@ const ru = {
1742
1995
  passwordMismatchError: "Пароли не совпадают",
1743
1996
  passwordTooShortError: "Пароль должен содержать не менее 8 символов",
1744
1997
  submitButton: "Создать аккаунт",
1745
- submittingButton: "Создание аккаунта...",
1998
+ submittingButton: "Создание аккаунта…",
1746
1999
  hasAccountText: "Уже есть аккаунт?",
1747
2000
  signInText: "Войти",
1748
2001
  errors: {
@@ -1763,12 +2016,26 @@ const ru = {
1763
2016
  emailLabel: "Электронная почта",
1764
2017
  emailPlaceholder: "name@example.com",
1765
2018
  submitButton: "Отправить ссылку для сброса",
1766
- submittingButton: "Отправка...",
2019
+ submittingButton: "Отправка…",
1767
2020
  successTitle: "Проверьте почту",
1768
2021
  successDescription: "Мы отправили ссылку для сброса пароля на {{email}}. Пожалуйста, проверьте свою почту.",
1769
2022
  backToSignInText: "Вернуться к входу",
1770
2023
  rememberPasswordText: "Помните свой пароль?",
1771
2024
  signInText: "Войти",
2025
+ // objectui#3546 slice three — the SMS reset branch of the same form.
2026
+ phoneLabel: "Номер телефона",
2027
+ phonePlaceholder: "+1 555 000 0000",
2028
+ otpCodeLabel: "Код подтверждения",
2029
+ otpCodePlaceholder: "6-значный код",
2030
+ sendOtpButton: "Получить код",
2031
+ resendOtpCountdownText: "Отправить снова через {seconds} с",
2032
+ newPasswordLabel: "Новый пароль",
2033
+ newPasswordPlaceholder: "Введите новый пароль",
2034
+ resetButton: "Сбросить пароль",
2035
+ usePhoneResetText: "Сбросить по SMS-коду",
2036
+ useEmailResetText: "Сбросить по электронной почте",
2037
+ phoneSuccessTitle: "Пароль сброшен",
2038
+ phoneSuccessDescription: "Ваш пароль сброшен. Теперь вы можете войти с новым паролем.",
1772
2039
  },
1773
2040
  resetPassword: {
1774
2041
  title: "Установить новый пароль",
@@ -1807,6 +2074,8 @@ const ru = {
1807
2074
  backToLogin: "Вернуться ко входу",
1808
2075
  checkSpam: "Не получили письмо? Проверьте папку \"Спам\" или обратитесь в поддержку.",
1809
2076
  or: "Или",
2077
+ // objectui#3546 slice three.
2078
+ resendUnavailable: "Возможно, отправка писем не настроена для этой среды. Если проблема повторяется, обратитесь в поддержку.",
1810
2079
  },
1811
2080
  setup: {
1812
2081
  welcomeTitle: "Добро пожаловать в ObjectStack",
@@ -1845,6 +2114,9 @@ const ru = {
1845
2114
  invalidDescription: "В URL не указан код устройства.",
1846
2115
  loading: "Загрузка…",
1847
2116
  cancel: "Отмена",
2117
+ // objectui#3546 slice three — device-authorization plugin switched off.
2118
+ disabledTitle: "Авторизация устройств не включена",
2119
+ disabledDescription: "В этой инсталляции авторизация устройств не включена, поэтому это устройство здесь одобрить нельзя.",
1848
2120
  },
1849
2121
  shell: {
1850
2122
  tenantHostHint: "Вы входите в это рабочее пространство",
@@ -1884,6 +2156,29 @@ const ru = {
1884
2156
  },
1885
2157
  },
1886
2158
  },
2159
+ // objectui#3546 slice three — the /oauth/consent screen.
2160
+ oauth: {
2161
+ consent: {
2162
+ title: "{{appName}} запрашивает доступ к вашему аккаунту",
2163
+ request: "{{appName}} запрашивает разрешение{{suffix}}.",
2164
+ unknownApp: "приложение",
2165
+ willAllow: "Это приложение сможет:",
2166
+ scope: {
2167
+ openid: "Подтверждать вашу личность",
2168
+ profile: "Читать основной профиль (имя, фото)",
2169
+ email: "Читать ваш адрес электронной почты",
2170
+ offlineAccess: "Оставаться в системе (обновление доступа)",
2171
+ },
2172
+ deny: "Отклонить",
2173
+ authorize: "Разрешить",
2174
+ submitting: "Авторизация…",
2175
+ granted: "Доступ предоставлен",
2176
+ denied: "Доступ запрещён",
2177
+ noRedirect: "Сервер не вернул URL для перенаправления.",
2178
+ failed: "Не удалось выдать согласие",
2179
+ footer: "Вы можете отозвать доступ в любое время в настройках аккаунта.",
2180
+ },
2181
+ },
1887
2182
  profile: {
1888
2183
  title: "Профиль",
1889
2184
  subtitle: "Управляйте настройками своей учётной записи",
@@ -1945,6 +2240,8 @@ const ru = {
1945
2240
  invite: "Пригласить участника",
1946
2241
  members: "Участники",
1947
2242
  settings: "Настройки рабочего пространства",
2243
+ multiOrgDisabled: "Создание новых организаций отключено в этой среде.",
2244
+ createFailed: 'Не удалось создать рабочее пространство',
1948
2245
  },
1949
2246
  help: {
1950
2247
  onThisPage: "На этой странице",
@@ -1955,7 +2252,7 @@ const ru = {
1955
2252
  },
1956
2253
  sidebar: {
1957
2254
  packageManagement: "Управление пакетами",
1958
- searchNavigation: "Поиск по навигации...",
2255
+ searchNavigation: "Поиск по навигации…",
1959
2256
  settings: "Настройки",
1960
2257
  help: "Помощь",
1961
2258
  helpTooltip: "Помощь и документация",
@@ -1979,8 +2276,8 @@ const ru = {
1979
2276
  switchObject: "Сменить объект",
1980
2277
  connection: {
1981
2278
  connected: "Подключено",
1982
- connecting: "Подключение...",
1983
- reconnecting: "Переподключение...",
2279
+ connecting: "Подключение…",
2280
+ reconnecting: "Переподключение…",
1984
2281
  disconnected: "Отключено",
1985
2282
  error: "Ошибка подключения",
1986
2283
  },
@@ -2019,6 +2316,15 @@ const ru = {
2019
2316
  publishing: "Публикация…",
2020
2317
  published: "Опубликовано! Изменения вступили в силу.",
2021
2318
  publishFailed: "Не удалось опубликовать",
2319
+ // objectui#3546 slice six — seedWarn совпадает с console.ai.seedWarn по
2320
+ // английскому тексту, поэтому берём тот же перевод. В двух счётных
2321
+ // строках число вынесено в конец («…: {{count}}») — так пак пишет
2322
+ // количества, скобочные формы вида «файл(ов)» здесь не нужны.
2323
+ nothing: "Публиковать нечего.",
2324
+ probeWarn: "Опубликовано, но проверка выявила проблемы.",
2325
+ seedWarn: "Опубликовано, но часть примеров данных загрузить не удалось.",
2326
+ publishedVerified: "Опубликовано и проверено — активных строк примеров данных: {{count}}.",
2327
+ capabilityWarn: "Проверка при создании — несуществующих ссылок на возможности: {{count}}.",
2022
2328
  },
2023
2329
  title: "Главная",
2024
2330
  subtitle: "Панель вашего рабочего пространства",
@@ -2032,7 +2338,7 @@ const ru = {
2032
2338
  title: "Требует вашего внимания",
2033
2339
  empty: "Всё выполнено",
2034
2340
  },
2035
- loading: "Загрузка рабочего пространства...",
2341
+ loading: "Загрузка рабочего пространства…",
2036
2342
  recent: "Недавние",
2037
2343
  starred: "Избранные",
2038
2344
  welcome: "Добро пожаловать в ObjectUI",
@@ -2093,6 +2399,9 @@ const ru = {
2093
2399
  roles: "Роли",
2094
2400
  configuration: "Конфигурация",
2095
2401
  createApp: "Создать приложение",
2402
+ administration: "Администрирование",
2403
+ datasources: "Источники данных",
2404
+ documentation: "Документация",
2096
2405
  },
2097
2406
  appSwitcher: {
2098
2407
  switchApplication: "Сменить приложение",
@@ -2132,7 +2441,7 @@ const ru = {
2132
2441
  search: {
2133
2442
  title: "Поиск",
2134
2443
  back: "Назад",
2135
- placeholder: "Поиск объектов, панелей, страниц, отчётов...",
2444
+ placeholder: "Поиск объектов, панелей, страниц, отчётов…",
2136
2445
  inputAriaLabel: "Поиск объектов, панелей, страниц, отчётов",
2137
2446
  resultsCount: "{{count}} результат для \"{{query}}\"",
2138
2447
  resultsCountPlural: "{{count}} результатов для \"{{query}}\"",
@@ -2151,6 +2460,7 @@ const ru = {
2151
2460
  empty: {
2152
2461
  objectNotFound: "Объект не найден",
2153
2462
  objectNotFoundDescription: "Определение объекта \"{{name}}\" отсутствует. Проверьте конфигурацию или вернитесь назад.",
2463
+ interfacePageSourceMissing: "Эта интерфейсная страница ссылается на \"{{name}}\", который недоступен.",
2154
2464
  pageNotFound: "Страница не найдена",
2155
2465
  pageNotFoundDescription: "Страница \"{{name}}\" не найдена. Возможно, она была удалена или переименована.",
2156
2466
  dashboardNotFound: "Панель не найдена",
@@ -2159,6 +2469,11 @@ const ru = {
2159
2469
  reportNotFoundDescription: "Отчёт \"{{name}}\" не найден. Возможно, он был удалён или переименован.",
2160
2470
  noAppsConfigured: "Нет приложений",
2161
2471
  noAppsConfiguredDescription: "Нет зарегистрированных приложений. Создайте первое приложение или посетите системные настройки.",
2472
+ appNotAvailable: "Приложение недоступно",
2473
+ appNotAvailableDescription: "Это приложение пока недоступно — возможно, публикация ещё идёт. Повторите попытку через мгновение.",
2474
+ appAccessDenied: "У вас нет доступа к этому приложению",
2475
+ appAccessDeniedDescription: "Это приложение существует, но у вашей учётной записи нет прав на его открытие. Обратитесь к администратору за доступом.",
2476
+ appAccessDeniedHome: "На главную",
2162
2477
  createFirstApp: "Создать приложение",
2163
2478
  systemSettings: "Системные настройки",
2164
2479
  back: "Назад",
@@ -2230,7 +2545,7 @@ const ru = {
2230
2545
  deleteFailed: "Не удалось удалить представление",
2231
2546
  },
2232
2547
  dashboardActions: {
2233
- pdfPreparing: "Подготовка экспорта PDF…",
2548
+ printDialogOpening: "Открывается диалог печати браузера (это не экспорт в PDF)",
2234
2549
  exportFailed: "Ошибка экспорта: {{message}}",
2235
2550
  forecastSoon: "Прогнозное представление скоро будет",
2236
2551
  },
@@ -2274,111 +2589,7 @@ const ru = {
2274
2589
  first: "Первый",
2275
2590
  },
2276
2591
  editor: {
2277
- breadcrumb: "Конфигурация",
2278
- basic: "Основное",
2279
- title: "Заголовок",
2280
- titlePlaceholder: "напр., Воронка по кварталам",
2281
- description: "Описание",
2282
- descriptionPlaceholder: "Что показывает этот отчёт?",
2283
- type: "Тип отчёта",
2284
- typeTabular: "Табличный — плоский список",
2285
- typeSummary: "Сводный — группировка с итогами",
2286
- typeMatrix: "Матричный — сводка строки × столбцы",
2287
- typeJoined: "Объединённый — несколько блоков",
2288
- typeHelp: "Выберите макет, который соответствует тому, что хотите увидеть.",
2289
- data: "Данные",
2290
- objectName: "Источник данных",
2291
- objectNamePlaceholder: "напр., opportunity",
2292
- objectNameHelp: "К какому объекту обращается этот отчёт?",
2293
- limit: "Лимит строк",
2294
- limitPlaceholder: "напр., 100",
2295
- columns: "Столбцы",
2296
- columnsHint: "Выберите поля для столбцов. В сводных и матричных отчётах добавляйте агрегаты (Сумма, Количество…).",
2297
- filters: "Фильтры",
2298
- filtersHint: "Ограничьте строки, попадающие в отчёт.",
2299
- filtersComplex: "В отчёте используется расширенный фильтр, который нельзя редактировать здесь. При сохранении он останется без изменений.",
2300
- groupBy: "Группировать по",
2301
- groupByHint: "Сгруппируйте данные и посчитайте промежуточные итоги.",
2302
- rows: "Строки",
2303
- rowsHint: "Сгруппировать строки по этим полям.",
2304
- columnsAxis: "Столбцы",
2305
- columnsAxisHint: "Развернуть эти поля по горизонтали.",
2306
- values: "Значения",
2307
- valuesHint: "Числа в каждой ячейке. Выберите одно или несколько полей и задайте агрегат (Сумма, Количество…).",
2308
- grouping: "Группировка",
2309
- addGrouping: "Добавить группировку",
2310
- dateGranularity: "Гранулярность даты",
2311
- dateGranularityNone: "(исходное значение)",
2312
- day: "День",
2313
- week: "Неделя",
2314
- month: "Месяц",
2315
- quarter: "Квартал",
2316
- year: "Год",
2317
- sortAsc: "По возрастанию",
2318
- sortDesc: "По убыванию",
2319
- chart: "График",
2320
- chartHint: "Дополнительная визуализация рядом с таблицей.",
2321
- chartType: "Тип графика",
2322
- chartTitle: "Заголовок графика",
2323
- chartTitlePlaceholder: "По умолчанию — заголовок отчёта",
2324
- chartXAxis: "Ось X (категория)",
2325
- chartYAxis: "Ось Y (значение)",
2326
- chartShowLegend: "Показывать легенду",
2327
- chartShowDataLabels: "Показывать подписи данных",
2328
- chartNone: "(без графика)",
2329
- chartBar: "Столбчатый",
2330
- chartLine: "Линейный",
2331
- chartArea: "Областной",
2332
- chartPie: "Круговой",
2333
- chartDonut: "Кольцевой",
2334
- chartFunnel: "Воронка",
2335
- validationNeedsObject: "Выберите источник данных перед добавлением столбцов.",
2336
- validationMatrixNeedsRowsCols: "Для матричного отчёта нужны хотя бы одна строка и один столбец.",
2337
- validationSummaryNeedsRows: "Для сводного отчёта нужно хотя бы одно поле группировки.",
2338
- blocks: "Блоки",
2339
- blocksHint: "Каждый блок — отдельная таблица или график. Фильтры блока объединяются с фильтром отчёта по И.",
2340
- addBlock: "Добавить блок",
2341
- removeBlock: "Удалить блок",
2342
- blockName: "Имя блока",
2343
- blockNamePlaceholder: "уникальное_имя_блока",
2344
- blockLabel: "Отображаемое название",
2345
- blockLabelPlaceholder: "Показывается над блоком",
2346
- blockDescription: "Описание",
2347
- blockDescriptionPlaceholder: "Необязательный контекст для блока",
2348
- validationJoinedNeedsBlocks: "Объединённый отчёт должен содержать хотя бы один блок.",
2349
- validationBlockNameRequired: "У каждого блока должно быть непустое имя.",
2350
- validationBlockNameDuplicate: "Имена блоков в отчёте должны быть уникальными.",
2351
- validationBlockNeedsColumns: "В каждом блоке должна быть хотя бы одна колонка.",
2352
- noneOption: "(нет)",
2353
- addCondition: "Добавить условие",
2354
- combineLogic: "Объединить с",
2355
- opContains: "содержит",
2356
- opIsEmpty: "пусто",
2357
- opIsNotEmpty: "не пусто",
2358
- formatAuto: "Авто",
2359
- formatCurrency: "Валюта",
2360
- formatPercent: "Процент",
2361
- formatInteger: "Целое число",
2362
- formatDate: "Дата",
2363
- formatDatetime: "Дата и время",
2364
- columnLabelPlaceholder: "Переопределить подпись",
2365
- aggregateColumn: "Агрегат",
2366
- formatColumn: "Формат",
2367
- addColumns: "Добавить столбцы",
2368
- searchFields: "Поиск полей…",
2369
- noMatchingFields: "Нет полей, соответствующих запросу.",
2370
- noFieldsAvailable: "Полей нет.",
2371
- columnsCount: "{n} столбец(ов) выбрано",
2372
- columnsEmpty: "Столбцы ещё не выбраны.",
2373
- fieldPickerTitle: "Выбрать поля",
2374
- fieldPickerDescription: "Выберите одно или несколько полей для добавления. Используйте поиск для фильтрации.",
2375
- fieldPickerChangeTitle: "Изменить поле",
2376
- fieldPickerAddGroupingTitle: "Добавить группировку",
2377
- fieldPickerEmpty: "(Выбрать поле)",
2378
- fieldPickerSelected: "{n} выбрано",
2379
- fieldPickerClear: "Сбросить выбор",
2380
- fieldPickerAdd: "Добавить",
2381
- fieldPickerAddN: "Добавить {n}",
2592
+ panelTitle: "Редактировать отчёт",
2382
2593
  },
2383
2594
  },
2384
2595
  organizations: {
@@ -2395,6 +2606,140 @@ const ru = {
2395
2606
  emptyDescription: "Создайте свою первую организацию, чтобы начать.",
2396
2607
  noMatches: "Нет организаций, соответствующих запросу.",
2397
2608
  },
2609
+ organization: {
2610
+ roles: {
2611
+ owner: 'Владелец',
2612
+ admin: 'Администратор',
2613
+ delegatedAdmin: 'Делегированный администратор',
2614
+ member: 'Участник',
2615
+ },
2616
+ errors: {
2617
+ notAllowedToInvite: 'У вас нет прав приглашать пользователей в эту организацию.',
2618
+ notAllowedToInviteWithRole: 'У вас нет прав приглашать пользователя с этой ролью.',
2619
+ alreadyInvited: 'Этот пользователь уже приглашён в эту организацию.',
2620
+ organizationExists: 'Такая организация уже существует.',
2621
+ slugTaken: 'Этот идентификатор уже занят.',
2622
+ notAllowedToCreate: 'У вас нет прав создавать новую организацию.',
2623
+ notTheRecipient: 'Вы не являетесь получателем этого приглашения.',
2624
+ invitationNotFound: 'Это приглашение больше не существует или истекло.',
2625
+ unknown: 'Что-то пошло не так. Попробуйте ещё раз.',
2626
+ },
2627
+ backToList: "Назад к организациям",
2628
+ notFound: "Организация не найдена",
2629
+ notFoundDescription: "Эта организация не существует или у вас нет к ней доступа.",
2630
+ tabs: {
2631
+ members: "Участники",
2632
+ invitations: "Приглашения",
2633
+ settings: "Настройки",
2634
+ },
2635
+ members: {
2636
+ title: "Участники",
2637
+ inviteMember: "Пригласить участника",
2638
+ inviteRestrictedNote: "Только администраторы организации могут приглашать участников.",
2639
+ removeMember: "Удалить участника",
2640
+ removeConfirmTitle: "Удалить участника?",
2641
+ removeConfirmDescription: "{{name}} будет удалён из организации и сразу потеряет доступ.",
2642
+ removeConfirmAction: "Удалить",
2643
+ memberRemoved: "Участник удалён",
2644
+ removeFailed: "Не удалось удалить участника",
2645
+ roleUpdated: "Роль обновлена",
2646
+ roleUpdateFailed: "Не удалось обновить роль",
2647
+ memberActions: 'Действия с участником',
2648
+ loadFailed: 'Не удалось загрузить участников',
2649
+ },
2650
+ invitations: {
2651
+ title: "Приглашения",
2652
+ empty: "Приглашений нет.",
2653
+ expiresAt: "Истекает",
2654
+ linkCopied: "Ссылка на приглашение скопирована",
2655
+ copyFailed: "Не удалось скопировать ссылку",
2656
+ canceled: "Приглашение отменено",
2657
+ cancelFailed: "Не удалось отменить приглашение",
2658
+ cancelTitle: "Отменить приглашение?",
2659
+ cancelDescription: "Приглашение для {{email}} будет отозвано.",
2660
+ cancelAction: "Отменить приглашение",
2661
+ inviteTitle: "Пригласить участника",
2662
+ inviteDescription: "Человек получит приглашение вступить в эту организацию.",
2663
+ emailLabel: "Электронная почта",
2664
+ roleLabel: "Роль",
2665
+ placementLabel: "Назначение (необязательно)",
2666
+ placementDescription: "Применяется при принятии приглашения. Показаны только подразделения и должности, которые вы можете делегировать.",
2667
+ businessUnitLabel: "Бизнес-подразделение",
2668
+ businessUnitPlaceholder: "Без назначения",
2669
+ positionsLabel: "Должности",
2670
+ sendInvite: "Отправить приглашение",
2671
+ sentTitle: "Приглашение создано",
2672
+ sentDescription: "Отправьте ссылку ниже приглашённому. Чтобы принять приглашение, ему нужно войти в систему.",
2673
+ linkLabel: "Ссылка для принятия",
2674
+ invitedAs: "{{email}} приглашён как {{role}}",
2675
+ copyLinkLabel: 'Скопировать ссылку-приглашение',
2676
+ loadFailed: 'Не удалось загрузить приглашения',
2677
+ inviteFailed: 'Не удалось пригласить участника',
2678
+ status: {
2679
+ all: "Все",
2680
+ pending: "Ожидает",
2681
+ accepted: "Принято",
2682
+ rejected: "Отклонено",
2683
+ canceled: "Отменено",
2684
+ },
2685
+ },
2686
+ settings: {
2687
+ generalTitle: "Общие",
2688
+ generalDescription: "Обновите сведения об организации.",
2689
+ readOnlyNote: "Изменять настройки могут только владельцы.",
2690
+ nameLabel: "Название организации",
2691
+ slugLabel: "Слаг",
2692
+ logoLabel: "Логотип",
2693
+ logoUpload: "Загрузить",
2694
+ logoReplace: "Заменить",
2695
+ logoClear: "Удалить",
2696
+ logoUploaded: "Логотип загружен — сохраните, чтобы применить",
2697
+ logoUploadFailed: "Не удалось загрузить логотип",
2698
+ save: "Сохранить изменения",
2699
+ saved: "Настройки сохранены",
2700
+ saveFailed: "Не удалось сохранить настройки",
2701
+ leaveTitle: "Покинуть организацию",
2702
+ leaveDescription: "Вы потеряете доступ к этой организации.",
2703
+ leaveAction: "Покинуть",
2704
+ leaveConfirmTitle: "Покинуть организацию?",
2705
+ leaveConfirmDescription: "Вы уверены, что хотите покинуть {{name}}? Доступ будет потерян немедленно.",
2706
+ leaveConfirmAction: "Покинуть",
2707
+ leftOrg: "Вы покинули организацию",
2708
+ leaveFailed: "Не удалось покинуть организацию",
2709
+ dangerZone: "Опасная зона",
2710
+ deleteTitle: "Удалить организацию",
2711
+ deleteDescription: "Безвозвратно удалить эту организацию и все её данные.",
2712
+ deleteAction: "Удалить",
2713
+ deleteConfirmTitle: "Удалить организацию?",
2714
+ deleteConfirmDescription: "Это действие необратимо. Все данные будут удалены безвозвратно. Введите слаг организации для подтверждения.",
2715
+ deleteConfirmSlugLabel: "Введите «{{slug}}» для подтверждения",
2716
+ deleteConfirmAction: "Удалить организацию",
2717
+ deleted: "Организация удалена",
2718
+ deleteFailed: "Не удалось удалить организацию",
2719
+ },
2720
+ accept: {
2721
+ title: "Вас пригласили",
2722
+ description: "Вас пригласили присоединиться к {{orgName}} в роли {{role}}.",
2723
+ errorTitle: "Приглашение недоступно",
2724
+ goToOrgs: "Перейти к организациям",
2725
+ loading: "Загрузка приглашения…",
2726
+ organization: "Организация",
2727
+ role: "Роль",
2728
+ expiresAt: "Истекает",
2729
+ accept: "Принять приглашение",
2730
+ accepted: "Приглашение принято",
2731
+ acceptFailed: "Не удалось принять приглашение",
2732
+ decline: "Отклонить",
2733
+ declined: "Приглашение отклонено",
2734
+ declineFailed: "Не удалось отклонить приглашение",
2735
+ },
2736
+ switcher: {
2737
+ label: "Переключить организацию",
2738
+ groupLabel: "Рабочая организация",
2739
+ groupHint: "Новые записи создаются здесь. В представлениях отображаются данные из всех ваших организаций.",
2740
+ manageMembers: "Управление участниками",
2741
+ },
2742
+ },
2398
2743
  notifications: {
2399
2744
  regionLabel: "Уведомления",
2400
2745
  groupCount: "Уведомлений: {{count}}",
@@ -2408,6 +2753,9 @@ const ru = {
2408
2753
  viewApprovals: "Показать утверждения",
2409
2754
  noPendingApprovals: "Нет ожидающих утверждений",
2410
2755
  openApprovalsInbox: "Открыть входящие утверждений",
2756
+ badgeTotal: "Всего: {{total}}",
2757
+ badgeNotifications: "{{unread}} уведомлений",
2758
+ badgeApprovals: "{{approvals}} ожидающих утверждений",
2411
2759
  emptyUnread: "Всё прочитано",
2412
2760
  filterUnread: "Непрочитанные",
2413
2761
  filterAll: "Все",
@@ -2694,6 +3042,7 @@ const ru = {
2694
3042
  dismiss: "Закрыть",
2695
3043
  openOnCloud: "Открыть в облаке",
2696
3044
  backHome: "На главную",
3045
+ updateTo: "Обновить",
2697
3046
  },
2698
3047
  install: {
2699
3048
  dialogTitle: "Установить {{name}}",
@@ -2710,6 +3059,37 @@ const ru = {
2710
3059
  localManifestConflict: "{{message}}\nПримечание: Локальное приложение уже имеет этот manifest_id. Сначала удалите его из objectstack.config.ts.",
2711
3060
  localUnauthorized: "Сначала войдите в этот рантайм.",
2712
3061
  localMarketplaceUnavailable: "OS_CLOUD_URL не настроен.",
3062
+ updateTo: "Обновить → v{{version}}",
3063
+ installedVersion: "Установлено v{{version}}",
3064
+ },
3065
+ // objectui#3546 — the MarketplacePage "Your organization" strip.
3066
+ org: {
3067
+ heading: "Ваша организация",
3068
+ install: "Установить",
3069
+ installed: "Установлено {{name}}",
3070
+ installedBadge: "Установлено",
3071
+ installing: "Установка…",
3072
+ },
3073
+ // ADR-0025 PD4 §3.5/§3.11 — the pre-install consent panel
3074
+ // (PluginDisclosure.tsx). `runtime` is a CLOSED enum: spec
3075
+ // PluginRuntimeSchema = z.enum(['node', 'sandbox', 'worker']).
3076
+ disclosure: {
3077
+ containsCode: "Этот пакет содержит код",
3078
+ reviewed: "Проверено и одобрено",
3079
+ unreviewed: "Ещё не проверено",
3080
+ signed: "Подписано",
3081
+ grantsIntro: "При установке пакет получит:",
3082
+ services: "Сервисы платформы",
3083
+ hooks: "Хуки жизненного цикла",
3084
+ network: "Доступ к сети",
3085
+ fs: "Доступ к файловой системе",
3086
+ noPermissions: "Не запрашивает особых разрешений.",
3087
+ acknowledge: "Я понимаю, что этот пакет выполняет код и получает указанные выше разрешения.",
3088
+ runtime: {
3089
+ node: "В процессе · полное доверие",
3090
+ sandbox: "В песочнице",
3091
+ worker: "Вне процесса",
3092
+ },
2713
3093
  },
2714
3094
  uninstall: {
2715
3095
  confirm: "Удалить {{manifestId}} v{{version}}?\n\nКэшированный манифест будет удалён.",
@@ -2959,6 +3339,34 @@ const ru = {
2959
3339
  confirmNote: 'Публикация атомарно выпускает все {{count}} ожидающих черновиков этого пакета.',
2960
3340
  publishConfirm: 'Опубликовать всё',
2961
3341
  },
3342
+ // ADR-0045 — the materialized-but-unlisted app banner
3343
+ // (UnpublishedAppBar.tsx), sibling of draftBar above.
3344
+ unpublishedBar: {
3345
+ message: 'Неопубликованное приложение — полностью работает, но видно только создателям. Опубликуйте, чтобы его увидели ваши пользователи.',
3346
+ publish: 'Опубликовать',
3347
+ publishing: 'Публикация…',
3348
+ published: 'Опубликовано! Приложение теперь видно вашим пользователям.',
3349
+ publishFailed: 'Не удалось опубликовать',
3350
+ },
3351
+ // ADR-0067 — the append-only build/revert timeline (CommitTimeline.tsx);
3352
+ // `button` is the banner's entry point into it.
3353
+ history: {
3354
+ button: 'История',
3355
+ title: 'История сборок',
3356
+ description: 'Все изменения этого приложения, новые сверху. Любой шаг можно отменить — подтверждать публикацию не нужно.',
3357
+ loadFailed: 'Не удалось загрузить историю:',
3358
+ loadFailedUnavailable: 'Хранилище коммитов временно недоступно — это чтение не выполнено, поэтому история не показана. Повторите попытку через мгновение.',
3359
+ loading: 'Загрузка истории…',
3360
+ empty: 'Истории для этого приложения пока нет.',
3361
+ revertLabel: 'Изменение отменено',
3362
+ applyLabel: 'Изменение сборки',
3363
+ revert: 'отмена',
3364
+ items: 'элементов',
3365
+ revertAction: 'Отменить',
3366
+ reverted: 'Отменено — изменение возвращено.',
3367
+ revertFailed: 'Не удалось отменить',
3368
+ revertUnavailable: 'Хранилище коммитов временно недоступно — отмена могла не примениться. Откройте историю заново и проверьте, прежде чем повторять.',
3369
+ },
2962
3370
  },
2963
3371
  filterBuilder: {
2964
3372
  where: "Где",
@@ -3003,5 +3411,91 @@ const ru = {
3003
3411
  addSort: "Добавить сортировку",
3004
3412
  removeSort: "Удалить сортировку",
3005
3413
  },
3414
+ collaboration: {
3415
+ commentCount: "Комментариев: {{count}}",
3416
+ commentCountOne: "{{count}} комментарий",
3417
+ resolvedSuffix: " · Решено",
3418
+ sortComments: "Сортировка комментариев",
3419
+ sortOldest: "Сначала старые",
3420
+ sortNewest: "Сначала новые",
3421
+ resolve: "Решить",
3422
+ reopen: "Открыть заново",
3423
+ justNow: "только что",
3424
+ minutesAgo: "{{count}} мин назад",
3425
+ hoursAgo: "{{count}} ч назад",
3426
+ daysAgo: "{{count}} д назад",
3427
+ edited: "(изменено)",
3428
+ reactionCount: "Реакций: {{count}}",
3429
+ reactionCountOne: "{{count}} реакция",
3430
+ addThumbsUp: "Поставить лайк",
3431
+ reply: "Ответить",
3432
+ reactThumbsUp: "Отреагировать лайком",
3433
+ reactHeart: "Отреагировать сердечком",
3434
+ cancelReply: "Отменить ответ",
3435
+ replyingTo: "Ответ для {{name}}…",
3436
+ replyingToComment: "Ответ на комментарий…",
3437
+ commentPlaceholder: "Добавьте комментарий… (@ — упоминание)",
3438
+ send: "Отправить",
3439
+ presentUserCount: "Присутствует пользователей: {{count}}",
3440
+ presentUserCountOne: "Присутствует {{count}} пользователь",
3441
+ moreUserCount: "Ещё пользователей: {{count}}",
3442
+ moreUserCountOne: "Ещё {{count}} пользователь",
3443
+ userStatusTitle: "{{name}} ({{status}})",
3444
+ statusActive: "активен",
3445
+ statusIdle: "бездействует",
3446
+ statusAway: "отошёл",
3447
+ },
3448
+ wizard: {
3449
+ missingRequired: "Заполните обязательные поля: {{fields}}",
3450
+ },
3451
+ appManagement: {
3452
+ title: "Приложения",
3453
+ subtitle: "Управление всеми настроенными приложениями",
3454
+ newApp: "Новое приложение",
3455
+ searchLabel: "Поиск приложений",
3456
+ searchPlaceholder: "Поиск приложений…",
3457
+ selectedCount: "Выбрано: {{n}}",
3458
+ bulkEnable: "Включить",
3459
+ bulkDisable: "Отключить",
3460
+ selectAll: "Выбрать все ({{n}})",
3461
+ empty: "Приложения не найдены.",
3462
+ defaultBadge: "По умолчанию",
3463
+ active: "Активно",
3464
+ inactive: "Неактивно",
3465
+ selectApp: "Выбрать {{name}}",
3466
+ openApp: "Открыть приложение",
3467
+ openAppNamed: "Открыть {{name}}",
3468
+ editApp: "Редактировать приложение",
3469
+ editAppNamed: "Редактировать {{name}}",
3470
+ editWithAi: "Редактировать с ИИ",
3471
+ editWithAiNamed: "Редактировать {{name}} с ИИ",
3472
+ enableApp: "Включить приложение",
3473
+ disableApp: "Отключить приложение",
3474
+ enableAppNamed: "Включить {{name}}",
3475
+ disableAppNamed: "Отключить {{name}}",
3476
+ setDefault: "Установить по умолчанию",
3477
+ setDefaultNamed: "Установить {{name}} по умолчанию",
3478
+ deleteApp: "Удалить приложение",
3479
+ deleteAppNamed: "Удалить {{name}}",
3480
+ confirmDelete: "Нажмите ещё раз для подтверждения удаления",
3481
+ confirmDeleteNamed: "Подтвердить удаление {{name}}",
3482
+ toast: {
3483
+ noClient: "Не удаётся подключиться к службе метаданных",
3484
+ unknownError: "неизвестная ошибка",
3485
+ appEnabled: "{{name}} включено",
3486
+ appDisabled: "{{name}} отключено",
3487
+ toggleFailed: "Не удалось изменить состояние приложения: {{reason}}",
3488
+ setDefaultDone: "{{name}} установлено по умолчанию",
3489
+ setDefaultFailed: "Не удалось установить приложение по умолчанию: {{reason}}",
3490
+ appDeleted: "{{name}} удалено",
3491
+ deleteFailed: "Не удалось удалить приложение: {{reason}}",
3492
+ bulkEnabled: "Включено приложений: {{n}}",
3493
+ bulkDisabled: "Отключено приложений: {{n}}",
3494
+ bulkFailed: "Не удалось для {{n}}: {{details}}",
3495
+ bulkFailureEntry: "{{name}} ({{reason}})",
3496
+ bulkFailureJoiner: "; ",
3497
+ bulkOperationFailed: "Массовая операция не выполнена: {{reason}}",
3498
+ },
3499
+ },
3006
3500
  };
3007
3501
  export default ru;