Initial commit
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"Bash(python *)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
+106
@@ -0,0 +1,106 @@
|
|||||||
|
# Сводка изменений: Система локализации
|
||||||
|
|
||||||
|
## ✅ Выполнено
|
||||||
|
|
||||||
|
### 1. Создана структура локализации
|
||||||
|
```
|
||||||
|
lang/
|
||||||
|
├── README.md # Инструкция по добавлению языков
|
||||||
|
├── en.json # Английский язык
|
||||||
|
├── ru.json # Русский язык
|
||||||
|
└── kz.json # Казахский язык (пример)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Модифицирован бэкенд (main.py)
|
||||||
|
- ✅ Добавлена константа `LANG_DIR` для папки локализаций
|
||||||
|
- ✅ Функция `get_available_languages()` — сканирует папку lang
|
||||||
|
- ✅ Функция `load_language(lang_code)` — загружает JSON локализации
|
||||||
|
- ✅ API эндпоинт `GET /api/languages` — список доступных языков
|
||||||
|
- ✅ API эндпоинт `GET /api/language/{lang_code}` — получение переводов
|
||||||
|
- ✅ Поле `language` добавлено в `config.json` и `SettingsModel`
|
||||||
|
|
||||||
|
### 3. Модифицирован фронтенд (Vue 3)
|
||||||
|
- ✅ Реактивная система локализации с функцией `t(key, params)`
|
||||||
|
- ✅ Автоматическая загрузка языка при старте приложения
|
||||||
|
- ✅ Селектор языка в настройках
|
||||||
|
- ✅ Мгновенная смена языка без перезагрузки страницы
|
||||||
|
- ✅ Все текстовые строки заменены на вызовы `t()`
|
||||||
|
- ✅ Поддержка параметров в строках: `{id}`, `{words}`, `{error}`
|
||||||
|
|
||||||
|
### 4. Документация
|
||||||
|
- ✅ `lang/README.md` — инструкция по добавлению языков
|
||||||
|
- ✅ `LOCALIZATION.md` — техническая документация
|
||||||
|
- ✅ Обновлён основной `README.md`
|
||||||
|
|
||||||
|
## 🎯 Как это работает
|
||||||
|
|
||||||
|
### Добавление нового языка
|
||||||
|
1. Создайте файл `lang/код.json` (например, `de.json` для немецкого)
|
||||||
|
2. Скопируйте содержимое из `en.json` или `ru.json`
|
||||||
|
3. Переведите значения (не меняя ключи)
|
||||||
|
4. Перезапустите приложение
|
||||||
|
5. **Готово!** Язык автоматически появится в настройках
|
||||||
|
|
||||||
|
### Смена языка пользователем
|
||||||
|
1. Открыть настройки (⚙️)
|
||||||
|
2. Выбрать язык в выпадающем списке "🌍 Язык интерфейса"
|
||||||
|
3. Интерфейс мгновенно переключится
|
||||||
|
4. Сохранить настройки
|
||||||
|
|
||||||
|
## 📊 Статистика
|
||||||
|
|
||||||
|
- **Строк кода в main.py:** 1375 (было ~1246)
|
||||||
|
- **Файлов локализации:** 3 (en, ru, kz)
|
||||||
|
- **Локализованных строк:** ~50 ключей
|
||||||
|
- **API эндпоинтов:** +2 новых
|
||||||
|
|
||||||
|
## 🌍 Доступные языки
|
||||||
|
|
||||||
|
- 🇬🇧 **English** (`en.json`)
|
||||||
|
- 🇷🇺 **Русский** (`ru.json`)
|
||||||
|
- 🇰🇿 **Қазақша** (`kz.json`) — пример для демонстрации
|
||||||
|
|
||||||
|
## 🔧 Технические особенности
|
||||||
|
|
||||||
|
- **Динамическое обнаружение:** Новые языки обнаруживаются автоматически
|
||||||
|
- **Горячая замена:** Язык меняется без перезагрузки страницы
|
||||||
|
- **Параметризация:** Поддержка подстановки значений в строки
|
||||||
|
- **Fallback:** Если перевод не найден, показывается ключ
|
||||||
|
- **UTF-8:** Полная поддержка Unicode для всех языков
|
||||||
|
- **Реактивность:** Vue 3 автоматически обновляет интерфейс
|
||||||
|
|
||||||
|
## 🎨 Пример использования в коде
|
||||||
|
|
||||||
|
### Простая строка
|
||||||
|
```javascript
|
||||||
|
{{ t('app_title') }} // → "Readeck Importer"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Строка с параметрами
|
||||||
|
```javascript
|
||||||
|
{{ t('content_stats', { words: wordCount }) }} // → "симв. · 42 слов"
|
||||||
|
t('success_bookmark_created', { id: '123' }) // → "Успешно! Закладка создана (ID: 123)"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📝 Структура файла локализации
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"lang_name": "Название языка на этом языке",
|
||||||
|
"lang_code": "код_языка",
|
||||||
|
"ключ": "Переведённое значение",
|
||||||
|
"ключ_с_параметром": "Текст с {параметром}"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## ✨ Преимущества реализации
|
||||||
|
|
||||||
|
1. **Простота** — добавить язык = создать один JSON файл
|
||||||
|
2. **Автоматизация** — не нужно менять код для добавления языка
|
||||||
|
3. **Масштабируемость** — можно добавить неограниченное количество языков
|
||||||
|
4. **UX** — мгновенная смена языка без перезагрузки
|
||||||
|
5. **Поддержка** — легко обновлять и исправлять переводы
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Система готова к использованию!** 🚀
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
# Обновление: Добавлена система локализации
|
||||||
|
|
||||||
|
## Что изменилось
|
||||||
|
|
||||||
|
### 1. Создана папка `lang` с файлами локализации
|
||||||
|
- `en.json` — английский язык
|
||||||
|
- `ru.json` — русский язык
|
||||||
|
- `kz.json` — казахский язык (пример)
|
||||||
|
- `README.md` — инструкция по добавлению новых языков
|
||||||
|
|
||||||
|
### 2. Изменения в `main.py`
|
||||||
|
|
||||||
|
#### Бэкенд:
|
||||||
|
- Добавлена константа `LANG_DIR` для папки с локализациями
|
||||||
|
- Добавлена функция `get_available_languages()` — сканирует папку lang и возвращает список доступных языков
|
||||||
|
- Добавлена функция `load_language(lang_code)` — загружает файл локализации
|
||||||
|
- Добавлен эндпоинт `GET /api/languages` — возвращает список доступных языков
|
||||||
|
- Добавлен эндпоинт `GET /api/language/{lang_code}` — возвращает строки локализации для языка
|
||||||
|
- В `config.json` добавлено поле `language` (по умолчанию "ru")
|
||||||
|
- Обновлена модель `SettingsModel` с полем `language`
|
||||||
|
|
||||||
|
#### Фронтенд:
|
||||||
|
- Добавлены реактивные переменные:
|
||||||
|
- `availableLanguages` — список доступных языков
|
||||||
|
- `translations` — текущие строки локализации
|
||||||
|
- `currentLang` — текущий выбранный язык
|
||||||
|
- Добавлена функция `t(key, params)` — возвращает локализованную строку с подстановкой параметров
|
||||||
|
- Добавлена функция `loadLanguage(langCode)` — загружает локализацию
|
||||||
|
- Добавлена функция `changeLanguage(langCode)` — меняет язык интерфейса
|
||||||
|
- Все текстовые строки в интерфейсе заменены на вызовы `t('ключ')`
|
||||||
|
- В настройках добавлен селектор языка интерфейса
|
||||||
|
- При загрузке приложения автоматически загружается язык из настроек
|
||||||
|
|
||||||
|
### 3. Изменения в `config.json`
|
||||||
|
Теперь файл содержит дополнительное поле:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"readeck_url": "...",
|
||||||
|
"readeck_token": "...",
|
||||||
|
"public_host": "...",
|
||||||
|
"language": "ru"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Как использовать
|
||||||
|
|
||||||
|
### Смена языка интерфейса
|
||||||
|
1. Откройте настройки (кнопка ⚙️)
|
||||||
|
2. Выберите язык в выпадающем списке "🌍 Язык интерфейса"
|
||||||
|
3. Интерфейс сразу переключится на выбранный язык
|
||||||
|
4. Нажмите "Сохранить" чтобы сохранить выбор
|
||||||
|
|
||||||
|
### Добавление нового языка
|
||||||
|
1. Создайте файл `lang/код_языка.json` (например, `de.json` для немецкого)
|
||||||
|
2. Скопируйте структуру из `en.json` или `ru.json`
|
||||||
|
3. Переведите все значения (не меняя ключи)
|
||||||
|
4. Укажите `lang_name` и `lang_code`
|
||||||
|
5. Перезапустите приложение
|
||||||
|
6. Новый язык автоматически появится в настройках!
|
||||||
|
|
||||||
|
## Пример файла локализации
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"lang_name": "Deutsch",
|
||||||
|
"lang_code": "de",
|
||||||
|
"app_title": "Readeck Importer",
|
||||||
|
"app_subtitle": "Lokale Artikel mit Übersetzung in Readeck importieren",
|
||||||
|
"settings": "Einstellungen",
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Технические детали
|
||||||
|
|
||||||
|
- Локализация загружается асинхронно при старте приложения
|
||||||
|
- Язык сохраняется в `config.json` и восстанавливается при следующем запуске
|
||||||
|
- Система поддерживает параметры в строках: `{id}`, `{words}`, `{error}` и т.д.
|
||||||
|
- Если файл локализации не найден, используются ключи как fallback
|
||||||
|
- Все файлы должны быть в кодировке UTF-8
|
||||||
|
|
||||||
|
## Преимущества реализации
|
||||||
|
|
||||||
|
✅ **Простота добавления языков** — просто положите JSON-файл в папку `lang`
|
||||||
|
✅ **Автоматическое обнаружение** — новые языки появляются в интерфейсе без изменения кода
|
||||||
|
✅ **Горячая замена** — язык меняется мгновенно без перезагрузки страницы
|
||||||
|
✅ **Расширяемость** — легко добавить любое количество языков
|
||||||
|
✅ **Централизация** — все переводы в одном месте
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
# Readeck Local Importer
|
||||||
|
|
||||||
|
Локальный веб-сервис для импорта статей в [Readeck](https://readeck.org/) (self-hosted сервис «прочитать позже»). Позволяет загрузить текст, файл или статью по ссылке, перевести её, отредактировать метаданные и одной кнопкой создать закладку в Readeck.
|
||||||
|
|
||||||
|
Readeck умеет сохранять закладки только по URL, поэтому приложение поднимает временную ссылку на ваш контент в локальной сети и передаёт её Readeck — так локальный текст попадает в библиотеку как обычная статья.
|
||||||
|
|
||||||
|
## Возможности
|
||||||
|
|
||||||
|
- **Импорт по ссылке** — скачивает страницу и извлекает чистый текст статьи (`trafilatura`).
|
||||||
|
- **Загрузка файлов** `.txt`, `.html`, `.md` (+ drag & drop), автоопределение кодировки.
|
||||||
|
- **Форматы контента** — HTML, Markdown, простой текст.
|
||||||
|
- **Перевод** через Google (22 языка) с учётом лимитов на длину запроса.
|
||||||
|
- **Автозаполнение метаданных** из HTML-метатегов (заголовок, автор, описание, дата, сайт).
|
||||||
|
- **Предпросмотр** статьи ровно в том виде, в каком её увидит Readeck.
|
||||||
|
- **Санитизация HTML** перед публикацией (`bleach`).
|
||||||
|
- **Тест подключения** к Readeck прямо из настроек.
|
||||||
|
- **Локализация интерфейса** — поддержка нескольких языков с возможностью добавления новых.
|
||||||
|
- Тёмная тема, счётчик символов/слов, автосохранение черновика.
|
||||||
|
|
||||||
|
## Требования
|
||||||
|
|
||||||
|
- Python 3.9+
|
||||||
|
- Доступный сервер Readeck и API-токен к нему
|
||||||
|
|
||||||
|
## Установка
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install fastapi uvicorn pydantic beautifulsoup4 lxml httpx deep-translator markdown bleach trafilatura
|
||||||
|
```
|
||||||
|
|
||||||
|
## Запуск
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python main.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Сервер стартует на `http://0.0.0.0:8142`, браузер откроется автоматически на `http://127.0.0.1:8142`.
|
||||||
|
|
||||||
|
При первом запуске откроется окно настроек — укажите:
|
||||||
|
|
||||||
|
- **Readeck URL** — адрес вашего сервера Readeck (например `http://192.168.1.10:8000`)
|
||||||
|
- **API Токен** — токен из настроек Readeck (`Bearer`)
|
||||||
|
- **LAN IP** — IP этой машины в локальной сети (для callback-ссылки, по которой Readeck заберёт контент)
|
||||||
|
|
||||||
|
Нажмите «Проверить подключение», чтобы убедиться, что сервер и токен валидны, затем сохраните. Настройки записываются в `config.json`.
|
||||||
|
|
||||||
|
## Использование
|
||||||
|
|
||||||
|
1. Вставьте текст, загрузите/перетащите файл или импортируйте статью по ссылке.
|
||||||
|
2. При необходимости переведите контент и выберите его формат.
|
||||||
|
3. Заполните или автозаполните метаданные, добавьте теги.
|
||||||
|
4. Посмотрите предпросмотр и нажмите «Создать закладку».
|
||||||
|
|
||||||
|
## Файлы
|
||||||
|
|
||||||
|
- `main.py` — всё приложение (бэкенд FastAPI + фронтенд на Vue 3 / Tailwind).
|
||||||
|
- `config.json` — настройки подключения к Readeck и выбранный язык интерфейса.
|
||||||
|
- `lang/` — папка с файлами локализации интерфейса.
|
||||||
|
|
||||||
|
## Локализация
|
||||||
|
|
||||||
|
Приложение поддерживает несколько языков интерфейса. Доступные языки:
|
||||||
|
- 🇬🇧 English
|
||||||
|
- 🇷🇺 Русский
|
||||||
|
- 🇰🇿 Қазақша (Казахский)
|
||||||
|
|
||||||
|
### Смена языка
|
||||||
|
1. Откройте настройки (⚙️)
|
||||||
|
2. Выберите язык в списке "🌍 Язык интерфейса"
|
||||||
|
3. Язык изменится мгновенно
|
||||||
|
|
||||||
|
### Добавление нового языка
|
||||||
|
1. Создайте файл `lang/код_языка.json` (например, `de.json`)
|
||||||
|
2. Скопируйте структуру из `lang/en.json` или `lang/ru.json`
|
||||||
|
3. Переведите все значения (не меняя ключи)
|
||||||
|
4. Перезапустите приложение — новый язык появится автоматически!
|
||||||
|
|
||||||
|
Подробнее см. `lang/README.md` и `LOCALIZATION.md`.
|
||||||
|
|
||||||
|
## Примечания по безопасности
|
||||||
|
|
||||||
|
- `config.json` хранит API-токен в открытом виде. Не коммитьте файл в git; при необходимости перевыпустите токен.
|
||||||
|
- Сервис слушает `0.0.0.0:8142` **без аутентификации** и доступен всем в локальной сети. Эндпоинт импорта по URL скачивает произвольные адреса (потенциальный SSRF). Для домашней сети это обычно приемлемо; не выставляйте сервис в интернет без авторизации.
|
||||||
Binary file not shown.
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"readeck_url": "http://192.168.1.182:8000",
|
||||||
|
"readeck_token": "Ra5nCVmru35waFbZE9jDrNnYLbkptHc952qtMFPprJDyJCHZ",
|
||||||
|
"public_host": "192.168.1.151",
|
||||||
|
"language": "ru"
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
# Локализация / Localization
|
||||||
|
|
||||||
|
Эта папка содержит файлы локализации для интерфейса приложения.
|
||||||
|
|
||||||
|
## Как добавить новый язык
|
||||||
|
|
||||||
|
1. Создайте новый JSON-файл в этой папке с кодом языка в качестве имени файла, например: `de.json` для немецкого языка.
|
||||||
|
|
||||||
|
2. Скопируйте содержимое из `en.json` или `ru.json` в качестве шаблона.
|
||||||
|
|
||||||
|
3. Переведите все значения (правая часть после двоеточия) на ваш язык. **Не изменяйте ключи** (левая часть).
|
||||||
|
|
||||||
|
4. Обязательно укажите:
|
||||||
|
- `lang_name` — название языка на этом языке (например, "Deutsch" для немецкого)
|
||||||
|
- `lang_code` — код языка (должен совпадать с именем файла)
|
||||||
|
|
||||||
|
5. Сохраните файл в кодировке UTF-8.
|
||||||
|
|
||||||
|
6. Перезапустите приложение — новый язык автоматически появится в настройках!
|
||||||
|
|
||||||
|
## Структура файла локализации
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"lang_name": "Название языка",
|
||||||
|
"lang_code": "код",
|
||||||
|
"ключ": "Переведённое значение",
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Параметры в строках
|
||||||
|
|
||||||
|
Некоторые строки содержат параметры в фигурных скобках, например:
|
||||||
|
- `{id}` — будет заменён на ID закладки
|
||||||
|
- `{words}` — будет заменён на количество слов
|
||||||
|
- `{error}` — будет заменён на текст ошибки
|
||||||
|
|
||||||
|
**Не удаляйте эти параметры** при переводе, просто переместите их в нужное место в предложении.
|
||||||
|
|
||||||
|
## Доступные языки
|
||||||
|
|
||||||
|
- `en.json` — English (Английский)
|
||||||
|
- `ru.json` — Русский
|
||||||
|
- `kz.json` — Қазақша (Казахский)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Localization
|
||||||
|
|
||||||
|
This folder contains localization files for the application interface.
|
||||||
|
|
||||||
|
## How to add a new language
|
||||||
|
|
||||||
|
1. Create a new JSON file in this folder with the language code as the filename, e.g., `de.json` for German.
|
||||||
|
|
||||||
|
2. Copy the content from `en.json` or `ru.json` as a template.
|
||||||
|
|
||||||
|
3. Translate all values (right side after the colon) to your language. **Do not change the keys** (left side).
|
||||||
|
|
||||||
|
4. Make sure to specify:
|
||||||
|
- `lang_name` — the name of the language in that language (e.g., "Deutsch" for German)
|
||||||
|
- `lang_code` — language code (must match the filename)
|
||||||
|
|
||||||
|
5. Save the file in UTF-8 encoding.
|
||||||
|
|
||||||
|
6. Restart the application — the new language will automatically appear in settings!
|
||||||
|
|
||||||
|
## Localization file structure
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"lang_name": "Language name",
|
||||||
|
"lang_code": "code",
|
||||||
|
"key": "Translated value",
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameters in strings
|
||||||
|
|
||||||
|
Some strings contain parameters in curly braces, for example:
|
||||||
|
- `{id}` — will be replaced with bookmark ID
|
||||||
|
- `{words}` — will be replaced with word count
|
||||||
|
- `{error}` — will be replaced with error text
|
||||||
|
|
||||||
|
**Do not remove these parameters** when translating, just move them to the appropriate place in the sentence.
|
||||||
|
|
||||||
|
## Available languages
|
||||||
|
|
||||||
|
- `en.json` — English
|
||||||
|
- `ru.json` — Русский (Russian)
|
||||||
|
- `kz.json` — Қазақша (Kazakh)
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
{
|
||||||
|
"lang_name": "English",
|
||||||
|
"lang_code": "en",
|
||||||
|
"app_title": "Readeck Importer",
|
||||||
|
"app_subtitle": "Import local articles to Readeck with translation",
|
||||||
|
"settings": "Settings",
|
||||||
|
"theme_light": "Light theme",
|
||||||
|
"theme_dark": "Dark theme",
|
||||||
|
|
||||||
|
"section_upload": "Upload and Content",
|
||||||
|
"section_metadata": "Metadata",
|
||||||
|
"section_readeck": "Readeck Options",
|
||||||
|
|
||||||
|
"import_url": "Import from URL",
|
||||||
|
"import_url_placeholder": "https://example.com/article",
|
||||||
|
"import_url_button": "⬇️ Download",
|
||||||
|
"import_url_loading": "Loading...",
|
||||||
|
|
||||||
|
"file_upload": "File (.txt, .html, .md)",
|
||||||
|
|
||||||
|
"content_format": "Content Format",
|
||||||
|
"format_html": "HTML",
|
||||||
|
"format_markdown": "Markdown",
|
||||||
|
"format_text": "Text",
|
||||||
|
|
||||||
|
"content_label": "Content",
|
||||||
|
"content_placeholder": "Upload a file, drag it here, paste text, or import from URL...",
|
||||||
|
"content_stats": "chars · {words} words",
|
||||||
|
|
||||||
|
"translation": "Translation:",
|
||||||
|
"translate_button": "🔄 Translate",
|
||||||
|
"translating": "Translating...",
|
||||||
|
|
||||||
|
"preview_button": "👁️ Preview",
|
||||||
|
"preview_title": "Preview",
|
||||||
|
"preview_new_tab": "↗️ Open in new tab",
|
||||||
|
"preview_close": "✕ Close",
|
||||||
|
|
||||||
|
"autofill_button": "✨ Autofill",
|
||||||
|
"autofill_tooltip": "Fill from HTML meta tags",
|
||||||
|
|
||||||
|
"meta_title": "Title *",
|
||||||
|
"meta_title_placeholder": "My article",
|
||||||
|
"meta_authors": "Authors",
|
||||||
|
"meta_authors_placeholder": "John Doe",
|
||||||
|
"meta_date": "Date (ISO)",
|
||||||
|
"meta_date_placeholder": "2023-10-01",
|
||||||
|
"meta_description": "Description",
|
||||||
|
"meta_description_placeholder": "Brief description...",
|
||||||
|
"meta_site_name": "Site Name",
|
||||||
|
"meta_site_name_placeholder": "Local Source",
|
||||||
|
|
||||||
|
"tags_label": "🏷️ Tags",
|
||||||
|
"tags_placeholder": "tech, news, translated",
|
||||||
|
|
||||||
|
"favorite": "⭐ Add to Favorites",
|
||||||
|
"archive": "📦 Archive",
|
||||||
|
|
||||||
|
"submit_button": "🚀 Create Bookmark",
|
||||||
|
"submitting": "⏳ Sending to Readeck...",
|
||||||
|
|
||||||
|
"settings_title": "Settings",
|
||||||
|
"settings_readeck_url": "🌐 Readeck URL",
|
||||||
|
"settings_readeck_url_placeholder": "http://192.168.1.10:8000",
|
||||||
|
"settings_token": "🔑 API Token",
|
||||||
|
"settings_token_placeholder": "rdk_...",
|
||||||
|
"settings_lan_ip": "📡 Your LAN IP",
|
||||||
|
"settings_lan_ip_placeholder": "192.168.x.x",
|
||||||
|
"settings_language": "🌍 Interface Language",
|
||||||
|
"settings_test": "🔌 Test Connection",
|
||||||
|
"settings_testing": "Testing...",
|
||||||
|
"settings_cancel": "Cancel",
|
||||||
|
"settings_save": "💾 Save",
|
||||||
|
|
||||||
|
"error_title_required": "Error: Title and Content are required!",
|
||||||
|
"success_bookmark_created": "Success! Bookmark created (ID: {id})",
|
||||||
|
"success_article_loaded": "✅ Article loaded and metadata filled",
|
||||||
|
"error_loading": "Loading error:\\n{error}",
|
||||||
|
"error_translation": "Translation error:\\n{error}",
|
||||||
|
"error_settings_save": "Failed to save settings:\\n{error}",
|
||||||
|
"error_network": "Network error while saving:\\n{error}",
|
||||||
|
"error_file_read": "Failed to read file:\\n{error}",
|
||||||
|
"error_metadata": "Failed to extract metadata:\\n{error}",
|
||||||
|
"error_preview": "Failed to build preview:\\n{error}",
|
||||||
|
"error_submit": "Error:\\n{error}",
|
||||||
|
|
||||||
|
"test_success": "✅ Connection successful",
|
||||||
|
"test_error": "❌ {error}"
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
{
|
||||||
|
"lang_name": "Қазақша",
|
||||||
|
"lang_code": "kz",
|
||||||
|
"app_title": "Readeck Importer",
|
||||||
|
"app_subtitle": "Readeck-ке аудармамен жергілікті мақалаларды импорттау",
|
||||||
|
"settings": "Баптаулар",
|
||||||
|
"theme_light": "Ашық тақырып",
|
||||||
|
"theme_dark": "Қараңғы тақырып",
|
||||||
|
|
||||||
|
"section_upload": "Жүктеу және Мазмұн",
|
||||||
|
"section_metadata": "Метадеректер",
|
||||||
|
"section_readeck": "Readeck опциялары",
|
||||||
|
|
||||||
|
"import_url": "Сілтеме бойынша импорттау",
|
||||||
|
"import_url_placeholder": "https://example.com/article",
|
||||||
|
"import_url_button": "⬇️ Жүктеу",
|
||||||
|
"import_url_loading": "Жүктелуде...",
|
||||||
|
|
||||||
|
"file_upload": "Файл (.txt, .html, .md)",
|
||||||
|
|
||||||
|
"content_format": "Мазмұн форматы",
|
||||||
|
"format_html": "HTML",
|
||||||
|
"format_markdown": "Markdown",
|
||||||
|
"format_text": "Мәтін",
|
||||||
|
|
||||||
|
"content_label": "Мазмұн",
|
||||||
|
"content_placeholder": "Файлды жүктеңіз, мұнда апарыңыз, мәтінді қойыңыз немесе сілтеме бойынша импорттаңыз...",
|
||||||
|
"content_stats": "таңба · {words} сөз",
|
||||||
|
|
||||||
|
"translation": "Аударма:",
|
||||||
|
"translate_button": "🔄 Аудару",
|
||||||
|
"translating": "Аударылуда...",
|
||||||
|
|
||||||
|
"preview_button": "👁️ Алдын ала қарау",
|
||||||
|
"preview_title": "Алдын ала қарау",
|
||||||
|
"preview_new_tab": "↗️ Жаңа қойындыда ашу",
|
||||||
|
"preview_close": "✕ Жабу",
|
||||||
|
|
||||||
|
"autofill_button": "✨ Автотолтыру",
|
||||||
|
"autofill_tooltip": "HTML мета тегтерінен толтыру",
|
||||||
|
|
||||||
|
"meta_title": "Тақырып *",
|
||||||
|
"meta_title_placeholder": "Менің мақалам",
|
||||||
|
"meta_authors": "Авторлар",
|
||||||
|
"meta_authors_placeholder": "Иван Иванов",
|
||||||
|
"meta_date": "Күні (ISO)",
|
||||||
|
"meta_date_placeholder": "2023-10-01",
|
||||||
|
"meta_description": "Сипаттама",
|
||||||
|
"meta_description_placeholder": "Қысқаша сипаттама...",
|
||||||
|
"meta_site_name": "Сайт атауы",
|
||||||
|
"meta_site_name_placeholder": "Жергілікті көз",
|
||||||
|
|
||||||
|
"tags_label": "🏷️ Тегтер",
|
||||||
|
"tags_placeholder": "tech, news, translated",
|
||||||
|
|
||||||
|
"favorite": "⭐ Таңдаулыларға қосу",
|
||||||
|
"archive": "📦 Мұрағатқа",
|
||||||
|
|
||||||
|
"submit_button": "🚀 Бетбелгі жасау",
|
||||||
|
"submitting": "⏳ Readeck-ке жіберілуде...",
|
||||||
|
|
||||||
|
"settings_title": "Баптаулар",
|
||||||
|
"settings_readeck_url": "🌐 Readeck URL",
|
||||||
|
"settings_readeck_url_placeholder": "http://192.168.1.10:8000",
|
||||||
|
"settings_token": "🔑 API токені",
|
||||||
|
"settings_token_placeholder": "rdk_...",
|
||||||
|
"settings_lan_ip": "📡 Сіздің LAN IP",
|
||||||
|
"settings_lan_ip_placeholder": "192.168.x.x",
|
||||||
|
"settings_language": "🌍 Интерфейс тілі",
|
||||||
|
"settings_test": "🔌 Қосылымды тексеру",
|
||||||
|
"settings_testing": "Тексерілуде...",
|
||||||
|
"settings_cancel": "Болдырмау",
|
||||||
|
"settings_save": "💾 Сақтау",
|
||||||
|
|
||||||
|
"error_title_required": "Қате: Тақырып және Мазмұн міндетті!",
|
||||||
|
"success_bookmark_created": "Сәтті! Бетбелгі жасалды (ID: {id})",
|
||||||
|
"success_article_loaded": "✅ Мақала жүктелді және метадеректер толтырылды",
|
||||||
|
"error_loading": "Жүктеу қатесі:\\n{error}",
|
||||||
|
"error_translation": "Аударма қатесі:\\n{error}",
|
||||||
|
"error_settings_save": "Баптауларды сақтау мүмкін болмады:\\n{error}",
|
||||||
|
"error_network": "Сақтау кезінде желі қатесі:\\n{error}",
|
||||||
|
"error_file_read": "Файлды оқу мүмкін болмады:\\n{error}",
|
||||||
|
"error_metadata": "Метадеректерді алу мүмкін болмады:\\n{error}",
|
||||||
|
"error_preview": "Алдын ала қарауды құру мүмкін болмады:\\n{error}",
|
||||||
|
"error_submit": "Қате:\\n{error}",
|
||||||
|
|
||||||
|
"test_success": "✅ Қосылым сәтті",
|
||||||
|
"test_error": "❌ {error}"
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
{
|
||||||
|
"lang_name": "Русский",
|
||||||
|
"lang_code": "ru",
|
||||||
|
"app_title": "Readeck Importer",
|
||||||
|
"app_subtitle": "Импорт локальных статей в Readeck с переводом",
|
||||||
|
"settings": "Настройки",
|
||||||
|
"theme_light": "Светлая тема",
|
||||||
|
"theme_dark": "Тёмная тема",
|
||||||
|
|
||||||
|
"section_upload": "Загрузка и Контент",
|
||||||
|
"section_metadata": "Метаданные",
|
||||||
|
"section_readeck": "Опции Readeck",
|
||||||
|
|
||||||
|
"import_url": "Импорт по ссылке",
|
||||||
|
"import_url_placeholder": "https://example.com/article",
|
||||||
|
"import_url_button": "⬇️ Загрузить",
|
||||||
|
"import_url_loading": "Загрузка...",
|
||||||
|
|
||||||
|
"file_upload": "Файл (.txt, .html, .md)",
|
||||||
|
|
||||||
|
"content_format": "Формат контента",
|
||||||
|
"format_html": "HTML",
|
||||||
|
"format_markdown": "Markdown",
|
||||||
|
"format_text": "Текст",
|
||||||
|
|
||||||
|
"content_label": "Контент",
|
||||||
|
"content_placeholder": "Загрузите файл, перетащите его сюда, вставьте текст или импортируйте по ссылке...",
|
||||||
|
"content_stats": "симв. · {words} слов",
|
||||||
|
|
||||||
|
"translation": "Перевод:",
|
||||||
|
"translate_button": "🔄 Перевести",
|
||||||
|
"translating": "Перевод...",
|
||||||
|
|
||||||
|
"preview_button": "👁️ Предпросмотр",
|
||||||
|
"preview_title": "Предпросмотр",
|
||||||
|
"preview_new_tab": "↗️ В новой вкладке",
|
||||||
|
"preview_close": "✕ Закрыть",
|
||||||
|
|
||||||
|
"autofill_button": "✨ Автозаполнить",
|
||||||
|
"autofill_tooltip": "Заполнить из HTML-метатегов контента",
|
||||||
|
|
||||||
|
"meta_title": "Заголовок *",
|
||||||
|
"meta_title_placeholder": "Моя статья",
|
||||||
|
"meta_authors": "Авторы",
|
||||||
|
"meta_authors_placeholder": "Иван Иванов",
|
||||||
|
"meta_date": "Дата (ISO)",
|
||||||
|
"meta_date_placeholder": "2023-10-01",
|
||||||
|
"meta_description": "Описание",
|
||||||
|
"meta_description_placeholder": "Краткое описание...",
|
||||||
|
"meta_site_name": "Название сайта",
|
||||||
|
"meta_site_name_placeholder": "Local Source",
|
||||||
|
|
||||||
|
"tags_label": "🏷️ Теги",
|
||||||
|
"tags_placeholder": "tech, news, translated",
|
||||||
|
|
||||||
|
"favorite": "⭐ В Избранное",
|
||||||
|
"archive": "📦 В Архив",
|
||||||
|
|
||||||
|
"submit_button": "🚀 Создать закладку",
|
||||||
|
"submitting": "⏳ Отправка в Readeck...",
|
||||||
|
|
||||||
|
"settings_title": "Настройки",
|
||||||
|
"settings_readeck_url": "🌐 Readeck URL",
|
||||||
|
"settings_readeck_url_placeholder": "http://192.168.1.10:8000",
|
||||||
|
"settings_token": "🔑 API Токен",
|
||||||
|
"settings_token_placeholder": "rdk_...",
|
||||||
|
"settings_lan_ip": "📡 Ваш LAN IP",
|
||||||
|
"settings_lan_ip_placeholder": "192.168.x.x",
|
||||||
|
"settings_language": "🌍 Язык интерфейса",
|
||||||
|
"settings_test": "🔌 Проверить подключение",
|
||||||
|
"settings_testing": "Проверка...",
|
||||||
|
"settings_cancel": "Отмена",
|
||||||
|
"settings_save": "💾 Сохранить",
|
||||||
|
|
||||||
|
"error_title_required": "Ошибка: Заголовок и Контент обязательны!",
|
||||||
|
"success_bookmark_created": "Успешно! Закладка создана (ID: {id})",
|
||||||
|
"success_article_loaded": "✅ Статья загружена и метаданные заполнены",
|
||||||
|
"error_loading": "Ошибка загрузки:\\n{error}",
|
||||||
|
"error_translation": "Ошибка перевода:\\n{error}",
|
||||||
|
"error_settings_save": "Не удалось сохранить настройки:\\n{error}",
|
||||||
|
"error_network": "Сетевая ошибка при сохранении:\\n{error}",
|
||||||
|
"error_file_read": "Не удалось прочитать файл:\\n{error}",
|
||||||
|
"error_metadata": "Не удалось извлечь метаданные:\\n{error}",
|
||||||
|
"error_preview": "Не удалось построить предпросмотр:\\n{error}",
|
||||||
|
"error_submit": "Ошибка:\\n{error}",
|
||||||
|
|
||||||
|
"test_success": "✅ Подключение успешно",
|
||||||
|
"test_error": "❌ {error}"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user