// Русская локаль — источник правды ключей; en.ts/uk.ts типизируются как typeof ru.
// Namespaces по областям UI (см. план i18n): common, nav, stack, tree, list,
// options, projects, settings, taskui.
export default {
common: {
all: 'Все',
noProject: '— без проекта —',
none: '— нет —',
choose: '— выберите —',
notSet: '— не указано —',
error: 'Ошибка запроса',
save: 'Сохранить',
cancel: 'Отмена',
edit: 'Редактировать',
preview: 'Предпросмотр',
confirmTitle: 'Подтверждение',
delete: 'Удалить',
open: 'Открыть',
move: 'Переместить',
actions: 'Действия',
expand: 'Развернуть',
collapse: 'Свернуть',
deleteConfirmTask: 'Удалить задачу «{title}»? Действие необратимо.',
deleteConfirmProject: 'Удалить проект «{name}»? Задачи останутся, но без проекта.',
archive: 'В архив',
archiveTitle: 'Отправить в архив',
saved: 'Сохранено',
created: 'Создано',
create: 'Создать',
taskDeleted: 'Задача удалена',
loading: 'Загрузка…',
projectDeleted: 'Проект удалён',
taskApproved: 'Задача утверждена',
taskTaken: 'Задача взята в работу',
taskFinished: 'Задача завершена',
yes: 'Да',
no: 'Нет',
back: 'Назад',
},
nav: {
sections: 'Разделы',
subtitle: 'GNexus Tasks — личные задачи',
signIn: 'Войти',
account: 'Аккаунт',
signOut: 'Выйти',
task: 'Задача',
home: 'Главная',
stack: 'Стек входящих',
list: 'Список задач',
achievements: 'Достижения',
stats: 'Статистика',
projects: 'Проекты',
archive: 'Архив',
journal: 'Журнал',
options: 'Выдача задачи',
settings: 'Настройки',
extension: 'Расширение',
},
// Прогресс: общий для страницы «Достижения» и сада (сад отключён в 0.58,
// вернётся позже — тексты нейтральные, без растений и «садовника»)
progress: {
title: 'Достижения',
level: 'Уровень {n}',
xpTotal: '{n} XP',
levelProgress: 'До уровня: {xp} / {span} XP',
aboutOpen: 'Как это работает',
aboutTitle: 'Как это работает',
levelsTitle: 'Дерево званий',
levelsHint:
'Пороги XP и звания каждого уровня. Уровень растёт из опыта за задачи — ничего не сгорает и не отнимается.',
levelCurrent: 'текущий',
achievements: 'Достижения',
coins: 'монет: {n}',
coinsHint: 'Монеты за закрытые задачи, создание задач и проектов, новые уровни — копятся',
achDone: 'Все ступени пройдены (высшая — {r})',
achStep: 'Ступень: римская — номер, дробь — прогресс к следующей',
about: [
'Каждая закрытая задача приносит опыт и монеты — прогресс только растёт и никогда не уменьшается.',
'За закрытие начисляется XP: база 10 + бонус за приоритет задачи (до 15) + бонус за объём работы по оценке времени (до 15) + 10 за «ментально сложную» — честная награда за силу воли. Крупные и срочные дела ценнее.',
'Накопленный XP повышает уровень — от «Ростка» до «Легенды сада». Уровень не падает: XP не сгорает и не отнимается, даже если задачу удалить.',
'Монеты приходят за закрытые задачи (столько же, сколько XP), за создание задач и проектов и за новые уровни. Сейчас они копятся — пригодятся, когда сад вернётся.',
'Достижения отмечают вехи: закрытые задачи, уровни, разные проекты, часы работы, строгие дедлайны, «ментально сложные» задачи. У каждой ступени I, II, III — прогресс виден всегда.',
'Задача, закрытая из режима «3 вариантов», отмечается меткой «выбрал и сделал». Закрытие «не хочется делать» празднуется золотом — сила воли того стоила. Ничего не сгорает, серий и наказаний нет — только приятные награды.',
],
levels: [
'Росток',
'Сеянцев',
'Садовник',
'Огородник',
'Дендролог',
'Лесничий',
'Садовый мастер',
'Хранитель сада',
'Королевский садовник',
'Магистр садоводства',
'Ландшафтный архитектор',
'Хранитель легенд',
'Легенда сада',
],
ach: {
firstDone: 'Первый росток',
done10: 'Десяток',
level5: 'Высоты',
sprinter: 'Спринтер',
explorer: 'Разносторонний',
marathon: 'Марафонец',
deadlineBoss: 'Дедлайн-босс',
chooser: 'Выбрал и сделал',
willpower: 'Преодоление',
recurring: 'Ритм жизни',
projectDone: 'Проект под ключ',
},
achHint: {
firstDone: 'Закройте первую задачу — веха открыта.',
done10: 'Закройте 10, 50 и 100 задач — по ступени за каждую веху.',
level5: 'Достигните 5, 10 и 15 уровня.',
sprinter: 'Закройте 3, 10 и 25 задач за один день.',
explorer: 'Имейте закрытые задачи в 3, 5 и 8 разных проектах.',
marathon: 'Накопите 10, 50 и 100 часов работы над задачами — по факту или оценке.',
deadlineBoss: 'Закройте 5, 15 и 30 задач со строгим дедлайном-датой.',
chooser: 'Закройте 5, 25 и 50 задач, взятых из режима «3 вариантов».',
willpower: 'Закройте 5, 25 и 50 задач с меткой «не хочется делать».',
recurring: 'Закройте регулярную задачу.',
projectDone: 'Завершите проект целиком: все его задачи (от трёх) закрыты.',
},
},
garden: {
title: 'Сад',
plants: 'растений: {n}',
levelsHint:
'Пороги XP и награды каждого уровня: новые виды растений (цена семени) и расширения карты. Уровень растёт из опыта за задачи — ничего не сгорает.',
rewardCreateTask: 'создание задачи',
rewardCreateProject: 'создание проекта',
lastReward: 'Последняя награда за: {title} — {date}',
emptyTitle: 'Сад пока пуст',
emptyText: 'Закройте первую задачу — на грядке появится растение.',
coins: 'монет: {n}',
coinsHint: 'Валюта сада: тратится на рост растений и декорации',
shop: 'Маркет',
shopTitle: 'Маркет сада',
buy: 'Купить',
notEnoughCoins: 'Не хватает {n} монет',
lockedUntil: 'Откроется на уровне {n}',
expansion: 'Расширение сада',
expansionHint: 'Больше земли — {n} клеток к периметру карты',
expansionCurrent: 'Текущая карта: {cols}×{rows}',
expansionMax: 'Вся земля открыта',
inventory: 'Инвентарь',
inventoryHint: 'Перетащите декорацию или семя на карту; декорацию можно вернуть обратно',
inventoryEmpty: 'Пока пусто: купленные декорации ждут здесь — перетащите их на карту',
zoomIn: 'Приблизить',
zoomOut: 'Отдалить',
zoomReset: 'Сбросить вид',
fullscreen: 'Во весь экран',
fullscreenExit: 'Выйти из полного экрана',
boughtHint: 'Куплено: {name} — перетащите её из инвентаря под картой на сад',
decorations: 'Декорации',
decorationsHint: 'Украсьте сад — декорации не дают бонусов, только настроение',
unique: 'уникальная',
rareOnly: 'только редкие растения',
seeds: 'Семена растений',
seedsHint: 'Открытые уровнем виды можно купить: семя попадает в инвентарь — перетащите его на свободную клетку. Редкие/эпик рождаются только из задач.',
seedBought: 'Семя куплено — перетащите его из инвентаря на грядку',
speciesHint:
'Опыт открывает новые виды и землю, монеты покупают семена, рост и украшения. Вид фиксируется за растением в момент рождения.',
upgrade: 'Вырастить — {n} монет',
maxStage: 'Полностью выросло',
stage: { sprout: 'Росток', bush: 'Куст', bloom: 'Цветение' },
speciesNames: {
'ph-flower': 'Цветок',
'ph-leaf': 'Зелень',
'ph-tree-evergreen': 'Ель',
'ph-flower-lotus': 'Лотос',
'ph-cactus': 'Кактус',
'ph-tree': 'Дуб',
'ph-drop': 'Роса',
'ph-sun': 'Подсолнух',
'ph-tree-structure': 'Бонсай',
'ph-butterfly': 'Бабочий куст',
'ph-campfire': 'Рябина',
'ph-sparkle': 'Звездоцвет',
'ph-fire': 'Огнецвет',
},
decorNames: {
fence: 'Изгородь',
bush: 'Куст',
flowerbed: 'Клумба',
lantern: 'Фонарь',
bench: 'Лавочка',
birdbath: 'Поилка для птиц',
flag: 'Флюгер',
birdhouse: 'Скворечник',
gem: 'Садовый самоцвет',
pond: 'Пруд',
greenhouse: 'Теплица',
gazebo: 'Беседка',
},
},
gamify: {
praise: [
'Отлично сделано!',
'Готово — полдела!',
'Ещё один шаг впереди.',
'Красота!',
'Так держать!',
'Минус одна задача, плюс настроение.',
],
chosen: 'выбрал и сделал',
willpower: 'сила воли',
willpowerText: 'Сила воли! Это того стоило.',
coins: 'монет',
createdReward: 'Создано — капля опыта уже ваша',
daily: 'Ежедневная награда за визит',
// Мандат ИИ-агента (ТЗ 3.20): события приходят по SSE из чужой сессии —
// агент взял задачу или закрыл её и ждёт приёмки
claimed: 'Агент взял задачу в работу',
claimedText: '{name} взялась за дело — задачу не трогайте, пока она работает',
review: 'Работа ждёт приёмки',
reviewText: '«{title}» — посмотрите, что сделано, и примите или верните',
},
stats: {
title: 'Статистика',
modeDay: 'День',
modeWeek: 'Неделя',
modeMonth: 'Месяц',
today: 'Сегодня, {date}',
prevPeriod: 'Предыдущий период',
nextPeriod: 'Следующий период',
ofDays: 'из {n} дн.',
totalVs: 'За период закрыто: {n} · в предыдущий раз: {m}',
chartTitle: 'Закрытые задачи',
legendNow: 'Сейчас',
legendPrev: 'Предыдущий период',
heatmapHalf: 'Активность за полгода',
heatmapYear: 'Активность за год',
heatTasks: 'Задачи',
heatXp: 'XP',
heatLess: 'меньше',
heatMore: 'больше',
heatHalf: 'Полгода',
heatYear: 'Год',
emptyTitle: 'Пока нет данных',
emptyText: 'Закройте пару задач — и здесь появится динамика со сравнением.',
metric: {
closed: 'Закрыто задач',
xp: 'XP получено',
created: 'Создано задач',
hours: 'Часы работы',
activeDays: 'Дни с результатом',
},
},
home: {
title: 'Главное',
stackCount: 'в стеке: {n}',
activeCount: 'активных: {n}',
inProgress: 'В работе',
overdue: 'Просрочено',
deadlines: 'Дедлайны на неделю',
next: 'Следующие',
overview: 'Обзор',
projects: 'Активные проекты',
totalTasks: 'Всего задач',
doneMonth: 'Выполнено за месяц',
doneAll: 'Выполнено всего',
clearTitle: 'Всё спокойно',
clearText: 'Нет активных задач — самое время закрыть что-то из стека.',
},
stack: {
title: 'Стек входящих',
count: 'Задач в стеке: {n}',
quickPlaceholder: 'Закинуть задачу — только текст, остальное потом…',
quickAdd: 'Закинуть',
newTask: 'Новая задача',
added: 'Задача закинута в стек',
detailTitle: 'Детализация задачи',
emptyTitle: 'Стек пуст',
emptyText: 'Закиньте первую задачу — детализация подберётся автоматически.',
inStack: 'в стеке',
uploading: 'загрузка…',
proposal: 'Предложение ИИ:',
proposalPending: 'Детализация подбирается…',
approveProposal: 'Да, всё верно',
detail: 'Детализировать',
redetail: 'Переспросить ИИ',
deleteTask: 'Удалить задачу',
deleteAttachment: 'Удалить вложение',
promptProject: 'Название нового проекта:',
promptTag: 'Название нового тега:',
newProject: 'Новый проект',
newTag: 'Новый тег',
approve: 'Утвердить',
form: {
title: 'Заголовок',
description: 'Описание (Markdown, Ctrl+V — картинка)',
preview: 'Предпросмотр Markdown',
project: 'Проект',
tagsPlaceholder: 'Добавить тег…',
tags: 'Теги',
priority: 'Приоритет',
estimate: 'Оценка времени',
budget: 'Бюджет (в валюте настроек)',
cost: 'Оценка затрат (в валюте настроек)',
estimateLegend: 'Оценка',
extra: 'Дополнительно',
bugtrailDone: 'Заполнено из багрепорта',
bugtrailFailed: 'Отчёт BugTrail не открылся',
},
deadline: {
legend: 'Дедлайн',
date: 'Строгий — дата',
period: 'Нестрогий — период',
},
recur: {
legend: 'Тип задачи',
oneTime: 'Разовая',
recurring: 'Регулярная (повторяется)',
kind: 'Правило повторения',
interval: 'Интервал, дней',
weekdays: 'Дни недели',
monthlyDay: 'День месяца (1–31, без дня — последний)',
},
},
tree: {
addSubtask: 'Добавить подзадачу',
promptSubtask: 'Подзадача:',
},
task: {
notFoundTitle: 'Задача не найдена',
notFoundText: 'Возможно, задача удалена или ссылка устарела.',
proposalTitle: 'Предложение ИИ',
proposalHint: 'Проверьте детали и утвердите — задача попадёт в список.',
proposalNotRight: 'Не то',
description: 'Описание',
editTitle: 'Изменить название',
editDescription: 'Редактировать описание',
deadlineConflict: 'Дедлайн: либо дата, либо период — не оба',
descriptionEmpty: 'Описание пусто — детализируйте задачу.',
readmeFrom: 'README.md из репозитория',
attachments: 'Вложения',
fields: 'Параметры',
dates: 'Даты',
field: {
project: 'Проект',
taskType: 'Тип задачи',
priority: 'Приоритет',
estimate: 'Оценка времени',
actual: 'Фактически',
money: 'Деньги',
deadline: 'Дедлайн',
recurrence: 'Повторение',
created: 'Создана',
approved: 'Утверждена',
done: 'Завершена',
},
subtasks: 'Подзадачи',
noSubtasks: 'Подзадач нет',
statusTitle: 'Статус',
changeStatus: 'Изменить статус',
takeWork: 'Взять в работу',
finishWork: 'Завершено',
// Закрытие с комментарием (ТЗ 3.20): у агента он обязателен, у владельца —
// по желанию; из формы страницы задачи комментарий уходит в журнал
finishTitle: 'Завершить задачу?',
finishComment: 'Комментарий к закрытию (необязательно)',
mentallyHard: {
set: 'Не хочется делать',
unset: 'Снять «ментально сложная»',
badge: 'ментально сложная',
},
// Мандат ИИ-агента (ТЗ 3.20): пометки задачи и плашка аренды
mandate: {
eligible: 'Доступно для ИИ агента',
eligibleHint: 'Задачу сможет взять Нави — ИИ-агент. Без пометки она её не трогает.',
shortBadge: 'ИИ',
createdBadge: 'создано агентом',
createdBy: 'Задачу создал агент «{name}»',
agent: 'агент',
claimedUntil: 'Взято {name} · до {time}',
},
// Приёмка работы агента (ТЗ 3.20): работа закрыта, но не принята
accept: {
title: 'Приёмка работы',
pendingBadge: 'ждёт приёмки',
pendingHint: 'Задачу закрыл агент — работу нужно принять или вернуть',
hint: 'Задачу закрыл {name}. Посмотрите, что сделано, и примите работу или верните её.',
report: 'Отчёт агента',
accept: 'Принять',
reject: 'Вернуть в работу',
accepted: 'Работа принята',
rejected: 'Задача вернулась в работу',
rejectTitle: 'Вернуть задачу в работу?',
rejectComment: 'Что не так (необязательно)',
},
subtaskCreated: 'Подзадача создана — попала в стек на детализацию',
createdRaw: 'Задача попала в стек — детализируйте её там',
// Промпт для ИИ-агента (0.87): текст задачи, который владелец копирует и
// передаёт своему агенту. Только факты о задаче — что с ней делать, решает
// владелец, а не кнопка
ai: {
menu: 'Промпт для ИИ',
title: 'Промпт для ИИ-агента',
hint: 'Текст задачи для передачи ИИ-агенту. При необходимости поправьте и скопируйте.',
copy: 'Скопировать промпт',
close: 'Закрыть',
intro: 'Задача из GNexus Tasks.',
taskSection: 'Задача',
descriptionSection: 'Описание',
proposalSection: 'Детализация (предложение ИИ, не утверждено)',
subtasksSection: 'Подзадачи',
linkSection: 'Ссылка',
id: 'ID',
titleField: 'Заголовок',
status: 'Статус',
tags: 'Теги',
parentTask: 'Родительская задача',
eligible: 'Доступно для ИИ-агента',
eligibleYes: 'да',
eligibleNo: 'нет',
claimed: 'Взято в работу',
descriptionEmpty: 'Описание пусто.',
},
actions: 'Действия',
addTag: 'Добавить тег…',
// Проект задачи в меню карточки (0.82): перейти к проекту и перенести
// в другой — соседние пункты, это один вопрос «в каком проекте задача»
goToProject: 'Перейти к проекту',
moveToProject: 'Переместить в проект',
// Пункт меню карточки (0.83): «Переместить в проект» в китовом меню (220px)
// рвалось на две строки, а в самом меню вопрос звучит как «в какой проект»
moveToOther: 'В другой проект',
moveHint: 'Задача «{title}» уедет в выбранный проект',
moved: 'Задача перенесена в «{project}»',
movedOut: 'Задача вынута из проекта',
},
projectPage: {
notFoundTitle: 'Проект не найден',
notFoundText: 'Возможно, проект удалён или ссылка устарела.',
note: 'Заметка',
editNote: 'Редактировать заметку',
noteEmpty: 'Заметки пока нет — добавьте её через «Редактировать».',
// README репозитория (0.67) — второе описание, отдельной карточкой
readmeTitle: 'README из репозитория',
readmeMissing: 'README в репозитории не найден — проверьте ссылку в параметрах проекта.',
readmeError: 'Не получилось прочитать README — репозиторий не ответил.',
noteCollapsedHint: 'Заметка большая — показано начало',
noteExpand: 'Развернуть',
noteCollapse: 'Свернуть',
progress: 'Задачи проекта: {done}/{total}',
newTask: 'Новая задача',
taskCreated: 'Задача создана — попала в стек на детализацию',
promptTask: 'Новая задача проекта:',
emptyTitle: 'Задач нет',
emptyText: 'Создайте первую задачу проекта или ослабьте фильтры.',
tree: 'Дерево проекта',
stats: 'Статистика',
total: 'Всего задач',
doneN: 'Завершено',
inProgress: 'В работе',
toDo: 'К выполнению',
overdue: 'Просрочено',
taskCount: '{n} задач',
openSite: 'Открыть сайт',
// Активность проекта (0.83): та же сетка «как в GitHub», что в статистике,
// но по задачам одного проекта; полгода, карточка в сайдбаре страницы проекта
activity: 'Активность',
heatCell: '{date} — закрыто {done}, создано {created}',
// Облако тегов (0.83): клик по тегу ставит подстрочный фильтр по его имени
tagShow: 'Показать задачи с тегом «{name}»',
tagHide: 'Снять фильтр по тегу «{name}»',
tagCount: 'Задач с этим тегом: {n}',
},
list: {
title: 'Список задач',
count: 'Найдено: {n}',
emptyTitle: 'Ничего не найдено',
emptyText: 'Попробуйте ослабить фильтры или закиньте новую задачу в стек.',
filterStatus: 'Статус',
filterTag: 'Тег',
filterTagSearch: 'Поиск по тегу',
filterTagHint: 'Начните вводить название тега',
filterTagClear: 'Сбросить фильтр по тегу',
// Переключатель (0.74) вместо табов приоритета: фильтр остался один —
// «выше среднего» (high и urgent), поэтому подпись читается по-человечески
filterPrioritized: 'Приоритетные',
// Второй переключатель (0.91, ТЗ 3.5): оставить в списке только регулярные.
// Рядом с «Приоритетными» — два вопроса об одном списке читаются парой
filterRecurring: 'Регулярные',
noTagsFound: 'Теги не найдены',
// Приёмка (0.85, ТЗ 3.20): не статус, а отдельная вкладка-плоскость
tabReview: 'Ждёт приёмки',
filterCreated: 'Кто создал',
createdAll: 'Все задачи',
createdMe: 'Созданные мной',
createdAgent: 'Созданные агентом',
},
// Журнал действий (ТЗ 3.20): кто, что и когда делал с задачами
journal: {
title: 'Журнал',
count: 'Записей: {n}',
empty: 'Записей нет — тут появятся действия по задачам',
filterKind: 'Тип события',
filterKindAll: 'Все события',
filterActor: 'Актор',
filterActorAll: 'Все акторы',
filterProject: 'Проект',
filterProjectAll: 'Все проекты',
actorUser: 'Я',
actorAgent: 'Агент',
col: {
when: 'Когда',
event: 'Событие',
task: 'Задача',
project: 'Проект',
actor: 'Актор',
comment: 'Комментарий',
},
// Виды записей — значения из tasklog.py, читаются человеческими словами
kind: {
created: 'Задача создана',
eligible_changed: 'Доступность агенту',
claimed: 'Взята агентом',
released: 'Возвращена агентом',
status_changed: 'Смена статуса',
completed: 'Задача закрыта',
accepted: 'Работа принята',
rejected: 'Работа возвращена',
deleted: 'Задача удалена',
},
// Машинные коды комментария у смены флага (on/off) и удалённый проект
eligibleOn: 'Открыта для агента',
eligibleOff: 'Закрыта для агента',
projectGone: 'Проект удалён',
taskDeleted: 'Задача удалена — заголовок сохранён в записи',
via: {
ui: 'из интерфейса',
api: 'по API',
mcp: 'через MCP',
},
},
options: {
title: 'Выдача задачи',
done: 'Готово',
notNow: 'Не сейчас — другие варианты',
availableHours: 'Доступное время, часов',
suggest: 'Предложить',
choose: 'Делаем сейчас',
emptyTitle: 'Вариантов нет',
emptyText:
'Свободных задач под это время не нашлось — закиньте что-нибудь в стек или уменьшите время.',
},
projects: {
title: 'Проекты',
count: 'Проектов: {n}',
new: 'Новый проект',
emptyTitle: 'Проектов нет',
emptyText:
'Создайте проект — задачи можно будет группировать и добавлять заметки с ресурсами.',
prompt: 'Название нового проекта:',
promptLabel: 'Название проекта',
taskCounts: 'Задач закрыто {done}/{total}',
noTasksYet: 'Задач в проекте пока нет',
progressLabel: 'Закрыто {done} из {total}',
inProgress: '{n} в работе',
overdue: 'просрочено {n}',
nextDeadline: 'Ближайший дедлайн: {date}',
lastActivity: 'Последняя активность по задачам: {date}',
noActivity: 'без активности',
colorNone: 'Без цвета',
sitePlaceholder: 'https://example.com',
repositoryPlaceholder: 'https://git.example.com/owner/repo',
withTasks: 'С задачами',
withoutTasks: 'Без задач',
pinned: 'Закреплённые',
pinnedLabel: 'Закреплён',
pin: 'Закрепить',
unpin: 'Открепить',
archived: 'Проект отправлен в архив',
archiveConfirm:
'Отправить проект «{name}» и его задачи ({n}) в архив? Всё можно будет восстановить из архива.',
edit: 'Редактировать',
delete: 'Удалить проект',
form: {
name: 'Название',
relevance: 'Актуальность',
priority: 'Приоритет',
note: 'Заметка (Markdown: ссылки, контекст)',
preview: 'Предпросмотр',
color: 'Цвет',
siteUrl: 'Сайт',
repositoryUrl: 'Репозиторий',
},
},
pagination: {
prev: 'Назад',
next: 'Вперёд',
pageOf: 'Страница {n} из {m}',
aria: 'Постраничная навигация',
},
archive: {
title: 'Архив',
count: 'Проектов: {n}',
emptyTitle: 'Архив пуст',
emptyText: 'Сюда попадают проекты, отправленные в архив, — вместе со всеми задачами и историей.',
restore: 'Восстановить',
restored: '«{name}» восстановлен из архива',
deleteForever: 'Удалить навсегда',
deleteConfirm:
'Удалить «{name}» навсегда? Проект и все его задачи будут потеряны безвозвратно.',
banner: 'Проект в архиве — история доступна только для просмотра. Восстановите его, чтобы продолжить работу.',
},
settings: {
title: 'Настройки',
currencyTitle: 'Валюта бюджетов',
currencyHint:
'Единица выбирается один раз и применяется во всех суммах: бюджет задачи, оценка затрат.',
currencyUnit: 'Единица измерения',
saved: 'Сохранено — применяется во всех видах.',
languageTitle: 'Язык интерфейса',
languageHint:
'Выбранный язык применяется сразу. «Как в аккаунте» — язык берётся из gnexus auth.',
languageUnit: 'Язык',
languageAuto: 'Как в аккаунте (SSO)',
langRu: 'Русский',
langEn: 'English',
langUk: 'Українська',
mcpTokenTitle: 'Токены MCP',
mcpTokenHint:
'Токен для ИИ-агента (например, Claude): агент действует от вашего имени и видит только ваши данные. Значение показывается один раз при создании — сразу скопируйте и вставьте в конфиг агента.',
mcpTokenCreated: 'Токен создан. Больше он показан не будет — скопируйте сейчас.',
mcpTokenShown: 'Я сохранил токен',
mcpTokenCopyFailed: 'Не удалось скопировать — выделите и скопируйте вручную',
mcpTokenUnnamed: 'Без названия',
mcpTokenDelete: 'Отозвать',
mcpTokenNone: 'Токенов пока нет — создайте первый, чтобы подключить агента.',
mcpTokenLabel: 'Название (например, «ноутбук»)',
mcpTokenLabelPlaceholder: 'для чего этот агент',
mcpTokenCreate: 'Сгенерировать',
mcpOpen: 'Как подключить',
// Системные уведомления (ТЗ 3.21)
pushTitle: 'Уведомления',
pushHint:
'Системные уведомления на устройство — они приходят, даже когда приложение закрыто: агент взял задачу, работа ждёт приёмки, подошёл срок или пора по ритму.',
pushSwitch: 'Присылать уведомления на это устройство',
pushDevices: 'Подключённых устройств: {n}',
pushOn: 'Уведомления включены на этом устройстве.',
pushOff: 'Уведомления выключены на этом устройстве.',
pushDenied:
'Браузер запретил уведомления для этого сайта. Разрешение возвращают в настройках браузера, здесь его не спрашивают.',
pushUnsupported:
'Этот браузер не умеет системные уведомления или страница открыта без HTTPS. Установленное на телефон приложение подходит: на iPhone — с iOS 16.4.',
pushUnconfigured:
'Сервер не настроен для отправки уведомлений — нужны ключи VAPID в его окружении.',
pushRequestDenied:
'Браузер не показал запрос. Включите уведомления для сайта в настройках браузера и попробуйте снова.',
pushFailed: 'Не удалось включить уведомления',
quietSwitch: 'Не беспокоить с 22:00 до 09:00',
quietHint:
'В это окно напоминания молчат и в очередь не встают: как только окно кончится, придёт напоминание по сегодняшнему состоянию дел. О работе агента сообщаем и в тихие часы — она ждёт вашего решения.',
},
ext: {
title: 'Расширение быстрого захвата',
whatTitle: 'Что это такое',
whatText:
'Клик по иконке расширения в трее браузера — и задача в стеке, не открывая сервис. В попапе две вкладки: «Добавить» (первая строка — название, остальное — описание; можно выбрать проект) и «Активные» — только просмотр, клик по задаче открывает её в сервисе.',
tokenTitle: 'Шаг 1. Токен доступа',
tokenText:
'Расширение подключается персональным MCP-токеном (как ИИ-агенты): создайте его в «Настройках → Токены MCP» — значение показывается один раз.',
tokenButton: 'Открыть Настройки',
downloadTitle: 'Шаг 2. Скачать и распаковать',
downloadButton: 'Скачать ZIP',
downloadHint: 'Распакуйте архив в любую папку.',
installTitle: 'Шаг 3. Загрузить расширение в браузер',
chromeText:
'Chrome/Chromium: откройте chrome://extensions, включите «Developer mode» → «Load unpacked» → выберите распакованную папку.',
firefoxText:
'Firefox: откройте about:debugging#/runtime/this-firefox → «Load Temporary Add-on…» → файл manifest.json из архива.',
connectTitle: 'Шаг 4. Подключить',
connectText:
'Кликните по иконке расширения, вставьте токен из шага 1 и нажмите «Подключить». Отзыв токена в «Настройках» отключает расширение.',
pwaTitle: 'Доступно из веб-версии',
pwaNote:
'Страница скрыта в установленном приложении (PWA) — откройте сервис в обычной вкладке браузера.',
},
mcp: {
title: 'MCP для ИИ-агентов',
whatTitle: 'Что это такое',
whatText:
'В приложение встроен MCP-сервер (Model Context Protocol): ИИ-агенты подключаются к нему и работают с вашими задачами от вашего имени — создают, ищут, обновляют и закрывают их. Закрытие задачи агентом даёт те же награды, что и в приложении: XP, монеты, растение в саду; у регулярной задачи следующий экземпляр создаётся автоматически.',
toolsTitle: 'Инструменты',
toolsHint:
'Сервер сам объясняет агенту порядок работы: начинать с проектов, привязывать задачи к проекту, не придумывать идентификаторы и следовать подсказкам в ошибках.',
toolListProjects: 'список проектов: заметки, статус, число открытых задач',
toolGetProject: 'контекст проекта: заметка и открытые задачи',
toolCreateTask: 'создать задачу (достаточно заголовка, желательно с проектом)',
toolUpdateTask: 'обновить поля задачи; закрытие — status="done"',
toolCompleteTask: 'завершить задачу (можно указать фактическое время)',
toolListTasks: 'поиск и фильтры: проект, тег, статус, подстрока',
toolGetTask: 'полные данные задачи, включая вложения',
toolListTags: 'справочник тегов',
connectTitle: 'Как подключить агента',
connectText:
'Транспорт — Streamable HTTP. Адрес совпадает с адресом этого приложения. Для подключения понадобится токен доступа.',
connectUrlLabel: 'Адрес сервера',
connectTokenLabel: 'Токен доступа',
connectTokenText:
'Агент действует от вашего имени. Создайте персональный токен в Настройках — раздел «Токены MCP» — и вставьте его сюда.',
connectClaudeLabel: 'Claude Code — одна команда',
connectJsonLabel: 'Универсальный JSON (Claude Desktop и другие клиенты)',
copy: 'Скопировать',
copied: 'Адрес скопирован',
copyFailed: 'Не удалось скопировать',
projectTitle: 'Контекст проекта',
projectText:
'Агент видит ваши проекты с заметками и их открытые задачи. Сервер инструктирует агента начинать работу с проектов (list_projects → get_project), привязывать создаваемые задачи к проекту и перечитывать get_project, возвращаясь к разговору после перерыва, — так задачи не теряются вне контекста своего проекта.',
},
md: {
bold: 'Жирный',
boldText: 'жирный текст',
italic: 'Курсив',
italicText: 'курсивный текст',
heading: 'Заголовок',
list: 'Список',
checklist: 'Чек-лист',
link: 'Ссылка',
linkText: 'текст ссылки',
code: 'Код',
},
login: {
signIn: 'Войти через GNEXUS',
subtitle: 'Ваши задачи, проекты и сад — в одном месте',
},
duration: {
hours: 'Часы',
minutes: 'Минуты',
h: 'ч',
min: 'мин',
},
taskui: {
// Подсказка бейджа-ссылки проекта в карточке задачи (0.75)
openProject: 'Открыть проект',
priority: {
very_low: 'Очень низкий',
low: 'Низкий',
medium: 'Средний',
high: 'Высокий',
urgent: 'Срочно',
},
status: {
to_do: 'К выполнению',
in_progress: 'В работе',
done: 'Завершено',
cancelled: 'Отменено',
deferred: 'Отложено',
},
relevance: {
active: 'Активен',
paused: 'Приостановлен',
},
time: {
hm: '{h} ч {m} м',
h: '{h} ч',
m: '{m} м',
},
money: {
budget: 'бюджет {amount}',
estimate: 'оценка {amount}',
},
currency: {
UAH: '₴ Гривна (UAH)',
USD: '$ Доллар (USD)',
EUR: '€ Евро (EUR)',
GBP: '£ Фунт (GBP)',
PLN: 'zł Злотый (PLN)',
},
deadline: {
day: 'в течение дня',
week: 'в течение недели',
month: 'в течение месяца',
year: 'в течение года',
until: 'до {date}',
},
countdown: {
today: 'Сегодня',
tomorrow: 'Завтра',
// формы числа (0.69): «через 3 дня», «просрочено на 5 дней» — было «дн.»
inDays: 'Через {n} день | Через {n} дня | Через {n} дней',
overdueDays: 'Просрочено на {n} день | Просрочено на {n} дня | Просрочено на {n} дней',
},
// «Сколько назад» (0.69): три формы на локаль — одна, две-четыре, много
// (ru/uk), у en их две. Выбор формы и подстановку {n} делает tn()
// (`…One` — единственное число без числа: «месяц назад», а не «1 месяц назад»)
ago: {
today: 'Сегодня',
yesterday: 'Вчера',
days: '{n} день назад | {n} дня назад | {n} дней назад',
weeks: '{n} неделю назад | {n} недели назад | {n} недель назад',
weeksOne: 'неделю назад',
months: '{n} месяц назад | {n} месяца назад | {n} месяцев назад',
monthsOne: 'месяц назад',
years: '{n} год назад | {n} года назад | {n} лет назад',
yearsOne: 'год назад',
},
recur: {
kind: {
interval: 'Каждые N дней',
weekdays: 'Дни недели',
monthly: 'День месяца',
},
daily: 'ежедневно',
weekly: 'еженедельно',
everyN: 'каждые {n} дн.',
byWeekdays: 'по дням недели',
monthlyDay: 'ежемесячно {day}-го',
recurring: 'регулярная',
// Дата регулярной читается не как срок, а как «когда пора» (0.91): «до
// 11.10» значило бы «успей к», а повторяющаяся задача никуда не опаздывает
next: 'след. {date}',
// Подсказка к метке в списке (0.91, ТЗ 3.5): одной иконки мало — владелец
// спрашивал, как вообще устроена регулярная задача, и ответ живёт здесь
hintNext: 'Регулярная: {rule}. Следующий экземпляр — {date}',
hint: 'Регулярная: {rule}. После закрытия появится следующий экземпляр',
},
},
}