import os _TRANSLATIONS: dict[str, dict[str, str]] = {} def _r(key: str, text: str) -> str: _TRANSLATIONS.setdefault("ru", {})[key] = text return text def _e(key: str, text: str) -> str: _TRANSLATIONS.setdefault("en", {})[key] = text return text # ── app ──────────────────────────────────────────────────────── _r("app.help", "CashFlow Forecast — личная финансовая модель") # ── cmd.init ─────────────────────────────────────────────────── _r("cmd.init.help", "Создать пустую финансовую модель") _r("cmd.init.ok", "Пустая модель создана в {path}") # ── cmd.forecast ─────────────────────────────────────────────── _r("cmd.forecast.help", "Запустить прогноз денежных потоков") _r("cmd.forecast.opt.months", "Количество месяцев прогноза") _r("cmd.forecast.opt.currency", "Валюта отображения (по умолчанию — базовая валюта модели)") _r("cmd.forecast.title", "Прогноз на {months} мес. ({currency})") _r("cmd.forecast.col.account", "Счёт") _r("cmd.forecast.col.month", "Месяц") _r("cmd.forecast.col.balance", "Баланс") _r("cmd.forecast.col.income", "Доход") _r("cmd.forecast.col.expenses", "Расход") _r("cmd.forecast.total", "Итог: Баланс: {balance} | Доход: {income} | Расход: {expenses}") # ── cmd.scenario ────────────────────────────────────────────── _r("cmd.scenario.help", "Применить сценарий и показать прогноз") _r("cmd.scenario.arg.name", "Имя сценария: baseline, optimistic, pessimistic") _r("cmd.scenario.opt.months", "Количество месяцев") _r("cmd.scenario.err.unknown", "Неизвестный сценарий: {name}") _r("cmd.scenario.err.available", "Доступны: {scenarios}") _r("cmd.scenario.label", "Сценарий") _r("cmd.scenario.label.balance", "Баланс") _r("cmd.scenario.label.income", "Доход") _r("cmd.scenario.label.expenses", "Расход") # ── cmd.whatif ──────────────────────────────────────────────── _r("cmd.whatif.help", "What-if анализ с произвольными множителями") _r("cmd.whatif.opt.income", "Множитель дохода") _r("cmd.whatif.opt.expense", "Множитель расхода") _r("cmd.whatif.opt.growth", "Множитель роста активов") _r("cmd.whatif.opt.months", "Количество месяцев") _r("cmd.whatif.title", "What-if анализ") _r("cmd.whatif.params", "Доход x{income} | Расход x{expense} | Рост x{growth}") # ── cmd.compare ─────────────────────────────────────────────── _r("cmd.compare.help", "Сравнить все сценарии") _r("cmd.compare.opt.months", "Количество месяцев") _r("cmd.compare.title", "Сравнение сценариев ({currency})") _r("cmd.compare.col.scenario", "Сценарий") # ── cmd.import ──────────────────────────────────────────────── _r("cmd.import.help", "Импорт данных из Excel") _r("cmd.import.arg.path", "Путь к .xlsx файлу") _r("cmd.import.ok", "Импортировано: {accounts} счетов, {transactions} транзакций, " "{recurring} регулярных платежей, {assets} активов, {liabilities} обязательств") _r("cmd.import.base_currency", "Базовая валюта: {currency}") _r("cmd.import.err", "Ошибка импорта: {error}") # ── cmd.export ──────────────────────────────────────────────── _r("cmd.export.help", "Экспорт модели в Excel") _r("cmd.export.arg.path", "Путь для .xlsx файла") _r("cmd.export.ok", "Модель экспортирована в {path}") _r("cmd.export.err", "Ошибка экспорта: {error}") # ── cmd.analyze ─────────────────────────────────────────────── _r("cmd.analyze.help", "AI-анализ финансовой модели") _r("cmd.analyze.opt.months", "Количество месяцев для анализа") _r("cmd.analyze.title.prompt", "Промпт для AI") _r("cmd.analyze.title.summary", "Сводка") _r("cmd.analyze.base_currency", "Базовая валюта: {currency}") _r("cmd.analyze.stub", "AI-ответ: заглушка. Подключите реальный API в ai/assistant.py") # ── cmd.info ────────────────────────────────────────────────── _r("cmd.info.help", "Сводка всей финансовой модели") _r("cmd.info.metadata", "Метаданные") _r("cmd.info.base_currency", "Базовая валюта: {currency} ({symbol})") _r("cmd.info.accounts", "Счетов: {count}") _r("cmd.info.transactions", "Транзакций: {count}") _r("cmd.info.recurring", "Регулярных платежей: {count}") _r("cmd.info.assets", "Активов: {count}") _r("cmd.info.liabilities", "Обязательств: {count}") _r("cmd.info.rates", "Курсов валют: {count}") _r("cmd.info.more", "... и ещё {count} транзакций") # ── table headers ───────────────────────────────────────────── _r("table.accounts.title", "Счета") _r("table.accounts_config.title", "Счета") _r("table.accounts.col.name", "Название") _r("table.accounts.col.currency", "Валюта") _r("table.accounts.col.balance", "Баланс") _r("table.transactions.title", "Транзакции") _r("table.transactions.col.date", "Дата") _r("table.transactions.col.category", "Категория") _r("table.transactions.col.amount", "Сумма") _r("table.transactions.col.description", "Описание") _r("table.recurring.title", "Регулярные платежи") _r("table.recurring.col.period", "Период") _r("table.recurring.col.amount", "Сумма") _r("table.recurring.col.category", "Категория") _r("table.recurring.col.id", "ID") _r("table.recurring.col.start", "Начало") _r("table.recurring.col.end", "Конец") _r("table.assets.title", "Активы") _r("table.assets.col.id", "ID") _r("table.assets.col.name", "Название") _r("table.assets.col.value", "Стоимость") _r("table.assets.col.growth", "Рост (%)") _r("table.liabilities.title", "Обязательства") _r("table.liabilities.col.id", "ID") _r("table.liabilities.col.name", "Название") _r("table.liabilities.col.balance", "Долг") _r("table.liabilities.col.rate", "Ставка") _r("table.liabilities.col.payment", "Платёж") _r("table.rates.title", "Курсы валют") _r("table.rates.col.from", "Из") _r("table.rates.col.to", "В") _r("table.rates.col.rate", "Курс") _r("table.accounts_config.col.id", "ID") _r("table.accounts_config.col.name", "Название") _r("table.accounts_config.col.currency", "Валюта") _r("table.accounts_config.col.balance", "Баланс") # ── config ──────────────────────────────────────────────────── _r("config.help", "Управление моделью (счета, транзакции, валюты...)") _r("cmd.config.base_currency.help", "Показать или установить базовую валюту модели") _r("cmd.config.base_currency.arg", "Код валюты (RUB, USD, EUR...)") _r("cmd.config.base_currency.ok", "Базовая валюта установлена: {currency}") _r("cmd.config.base_currency.show", "Базовая валюта: {currency}") _r("cmd.config.rate_set.help", "Добавить или обновить курс валюты") _r("cmd.config.rate_set.arg.from", "Из валюты") _r("cmd.config.rate_set.arg.to", "В валюту") _r("cmd.config.rate_set.arg.rate", "Курс") _r("cmd.config.rate_set.ok", "Курс {fc} → {tc} = {rate}") _r("cmd.config.rate_list.help", "Список курсов валют") _r("cmd.config.rate_list.empty", "Курсы не заданы") _r("cmd.config.rate_remove.help", "Удалить курс валюты") _r("cmd.config.rate_remove.ok", "Курс {fc} → {tc} удалён") _r("cmd.config.rate_remove.err", "Курс {fc} → {tc} не найден") _r("cmd.config.account_add.help", "Добавить счёт") _r("cmd.config.account_add.opt.name", "Название счёта") _r("cmd.config.account_add.opt.balance", "Начальный баланс") _r("cmd.config.account_add.opt.currency", "Валюта счёта") _r("cmd.config.account_add.ok", "Счёт '{name}' добавлен (баланс: {balance}, валюта: {currency})") _r("cmd.config.account_list.help", "Список счетов") _r("cmd.config.account_list.empty", "Счета не добавлены") _r("cmd.config.account_remove.help", "Удалить счёт по ID или названию") _r("cmd.config.account_remove.arg", "ID или название счёта") _r("cmd.config.account_remove.ok", "Счёт '{id}' удалён") _r("cmd.config.account_remove.err", "Счёт '{id}' не найден") _r("cmd.config.transaction_add.help", "Добавить транзакцию") _r("cmd.config.transaction_add.opt.account", "ID или название счёта") _r("cmd.config.transaction_add.opt.amount", "Сумма (доход/расход)") _r("cmd.config.transaction_add.opt.category", "Категория") _r("cmd.config.transaction_add.opt.description", "Описание") _r("cmd.config.transaction_add.opt.date", "Дата (YYYY-MM-DD)") _r("cmd.config.transaction_add.ok", "Транзакция '{kind}' на {amount:.2f} (счёт: {account})") _r("cmd.config.transaction_add.kind.income", "доход") _r("cmd.config.transaction_add.kind.expense", "расход") _r("cmd.config.transaction_add.err", "Счёт '{account}' не найден") _r("cmd.config.transaction_list.help", "Список транзакций") _r("cmd.config.transaction_list.empty", "Транзакции не добавлены") _r("cmd.config.transaction_remove.help", "Удалить транзакцию по ID") _r("cmd.config.transaction_remove.arg", "ID транзакции") _r("cmd.config.transaction_remove.ok", "Транзакция '{id}' удалена") _r("cmd.config.transaction_remove.err", "Транзакция '{id}' не найдена") _r("cmd.config.recurring_add.help", "Добавить регулярный платёж") _r("cmd.config.recurring_add.opt.amount", "Сумма") _r("cmd.config.recurring_add.opt.category", "Категория") _r("cmd.config.recurring_add.opt.frequency", "Периодичность") _r("cmd.config.recurring_add.opt.start", "Дата начала (YYYY-MM-DD)") _r("cmd.config.recurring_add.opt.end", "Дата окончания (YYYY-MM-DD)") _r("cmd.config.recurring_add.ok", "Регулярный платёж на {amount:.2f} ({frequency})") _r("cmd.config.recurring_list.help", "Список регулярных платежей") _r("cmd.config.recurring_list.empty", "Регулярные платежи не добавлены") _r("cmd.config.recurring_remove.help", "Удалить регулярный платёж по ID") _r("cmd.config.recurring_remove.arg", "ID регулярного платежа") _r("cmd.config.recurring_remove.ok", "Регулярный платёж '{id}' удалён") _r("cmd.config.recurring_remove.err", "Регулярный платёж '{id}' не найден") _r("cmd.config.asset_add.help", "Добавить актив") _r("cmd.config.asset_add.opt.name", "Название актива") _r("cmd.config.asset_add.opt.value", "Стоимость") _r("cmd.config.asset_add.opt.growth", "Годовой рост (%)") _r("cmd.config.asset_add.ok", "Актив '{name}' добавлен (стоимость: {value})") _r("cmd.config.asset_list.help", "Список активов") _r("cmd.config.asset_list.empty", "Активы не добавлены") _r("cmd.config.asset_remove.help", "Удалить актив по ID или названию") _r("cmd.config.asset_remove.arg", "ID или название актива") _r("cmd.config.asset_remove.ok", "Актив '{id}' удалён") _r("cmd.config.asset_remove.err", "Актив '{id}' не найден") _r("cmd.config.liability_add.help", "Добавить обязательство") _r("cmd.config.liability_add.opt.name", "Название") _r("cmd.config.liability_add.opt.balance", "Остаток долга") _r("cmd.config.liability_add.opt.interest", "Процентная ставка (%)") _r("cmd.config.liability_add.opt.payment", "Ежемесячный платёж") _r("cmd.config.liability_add.ok", "Обязательство '{name}' добавлено (долг: {balance})") _r("cmd.config.liability_list.help", "Список обязательств") _r("cmd.config.liability_list.empty", "Обязательства не добавлены") _r("cmd.config.liability_remove.help", "Удалить обязательство по ID или названию") _r("cmd.config.liability_remove.arg", "ID или название обязательства") _r("cmd.config.liability_remove.ok", "Обязательство '{id}' удалено") _r("cmd.config.liability_remove.err", "Обязательство '{id}' не найдено") # ── global ───────────────────────────────────────────────────── _r("global.ok", "OK") # ── prompts ─────────────────────────────────────────────────── _r("prompt.analyze", ( "Ты — финансовый AI-ассистент. Проанализируй финансовую модель пользователя.\n" "\n" "### Модель (JSON):\n" "{model_json}\n" "\n" "### Прогноз на {months} месяцев:\n" "{forecast_json}\n" "\n" "### Валюта:\n" "Базовая валюта модели: {base_currency}\n" "Отображаемая валюта: {display_currency}\n" "\n" "Дай анализ по пунктам:\n" "1. Общее финансовое состояние\n" "2. Тренд денежного потока (рост/падение)\n" "3. Достаточность ликвидности\n" "4. Рекомендации по улучшению" )) _r("prompt.advice", ( "Ты — финансовый AI-ассистент. Дай персональные рекомендации.\n" "\n" "### Модель:\n" "{model_json}\n" "\n" "### Прогноз:\n" "{forecast_json}\n" "\n" "### Валюта:\n" "Базовая валюта модели: {base_currency}\n" "Отображаемая валюта: {display_currency}\n" "\n" "Вопрос пользователя: {question}\n" "\n" "Ответь как опытный финансовый консультант." )) _r("prompt.scenario_comparison", ( "Ты — финансовый AI-ассистент. Сравни сценарии прогноза.\n" "\n" "### Результаты сценариев:\n" "{scenarios_json}\n" "\n" "### Валюта:\n" "Базовая валюта модели: {base_currency}\n" "Отображаемая валюта: {display_currency}\n" "\n" "Дай рекомендацию: какой сценарий наиболее вероятен и почему." )) _current_lang = "ru" class Translator: def __init__(self, lang: str | None = None): self.lang = lang or _current_lang if self.lang not in _TRANSLATIONS: _TRANSLATIONS[self.lang] = {} def t(self, key: str, **kwargs) -> str: src = _TRANSLATIONS.get(self.lang) or _TRANSLATIONS.get("ru") or {} if key in src: template = src[key] elif "ru" in _TRANSLATIONS and key in _TRANSLATIONS["ru"]: template = _TRANSLATIONS["ru"][key] else: return key return template.format(**kwargs) if kwargs else template _GLOBAL = Translator() def setup_i18n() -> None: lang = os.environ.get("CF_LANG", "ru") if lang not in _TRANSLATIONS: _TRANSLATIONS[lang] = {} _GLOBAL.lang = lang def set_lang(lang: str) -> None: if lang not in _TRANSLATIONS: _TRANSLATIONS[lang] = {} _GLOBAL.lang = lang def get_lang() -> str: return _GLOBAL.lang def t(key: str, **kwargs) -> str: return _GLOBAL.t(key, **kwargs)