Files
blog.pyaqa.ru/app/infrastructure/i18n/translations.py
Sergey Vanyushkin d32ad29abc
Some checks failed
ci/woodpecker/pr/pipeline Pipeline failed
feat(i18n): add browser-language localization with Jinja2 _() and locale middleware
Add i18n support to the blog web UI with 4 languages (en/ru/fr/de),
80 translation keys, automatic Accept-Language detection, persistent
locale cookie, and a language switcher dropdown in the header.

- Infrastructure: TranslationService, translation dicts, convenience _()
- Presentation: locale middleware, /web/lang/{locale} switcher route
- Templates: all 9 templates use {{ _(key, current_locale) }}
- Tests: 26 tests across TranslationService, locale detection helpers
- Docs: TEST_MODEL.md and FEATURE_INFRASTRUCTURE.md updated with TC-UNIT-811-821
2026-05-10 16:22:06 +03:00

338 lines
18 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Translation dictionaries for i18n support.
This module provides translation dictionaries for all supported locales.
Translations are organized by feature area for maintainability.
Keys use dot-separated namespacing to avoid collisions.
"""
TRANSLATIONS: dict[str, dict[str, str]] = {
"en": {
"nav.home": "Home",
"nav.posts": "Posts",
"nav.about": "About",
"header.logo": "Blog",
"header.profile": "Profile",
"header.new_post": "New Post",
"header.sign_out": "Sign Out",
"header.sign_in": "Sign In",
"header.toggle_menu": "Toggle menu",
"header.toggle_theme": "Toggle dark mode",
"header.lang_switcher": "Language",
"footer.copyright": "© 2026 Blog. All rights reserved.",
"footer.about": "About",
"footer.privacy": "Privacy",
"footer.terms": "Terms",
"footer.api": "API",
"home.title": "Blog - Home",
"home.meta_description": "Discover stories, thinking, and expertise from writers on any topic. A modern blog built with FastAPI.",
"home.meta_keywords": "blog, articles, posts, writing, fastapi, python",
"home.page_title": "Latest Posts",
"home.page_subtitle": "Discover stories, thinking, and expertise from writers on any topic.",
"home.write_post": "Write a Post",
"home.status_published": "Published",
"home.status_draft": "Draft",
"home.read_more": "Read more",
"home.pagination_previous": "Previous",
"home.pagination_next": "Next",
"home.empty_title": "No posts yet",
"home.empty_description": "Be the first to write a post!",
"home.empty_action": "Create your first post",
"post.status_published": "Published",
"post.status_draft": "Draft",
"post.back_to_posts": "Back to posts",
"post.edit": "Edit",
"post.delete": "Delete",
"post.delete_confirm": "Are you sure you want to delete this post?",
"post_form.title_edit": "Edit Post",
"post_form.title_new": "New Post",
"post_form.page_title_edit": "Edit Post",
"post_form.page_title_new": "Create New Post",
"post_form.label_title": "Title",
"post_form.placeholder_title": "Enter post title",
"post_form.hint_title": "A catchy title for your post",
"post_form.label_content": "Content",
"post_form.placeholder_content": "Write your post content here...",
"post_form.hint_content": "The main content of your post. Markdown is supported.",
"post_form.label_tags": "Tags",
"post_form.placeholder_tags": "python, fastapi, tutorial",
"post_form.hint_tags": "Comma-separated list of tags",
"post_form.cancel": "Cancel",
"post_form.save_draft": "Save as Draft",
"post_form.update_post": "Update Post",
"post_form.publish_post": "Publish Post",
"profile.title": "User Profile",
"profile.email": "Email:",
"profile.not_provided": "Not provided",
"profile.user_id": "User ID:",
"profile.name": "Name:",
"profile.back_home": "Back to Home",
"profile.new_post": "New Post",
"about.title": "About",
"about.page_title": "About",
"about.description": "A modern blog built with FastAPI and Domain-Driven Design architecture.",
"about.signed_in": "Signed in as {username}.",
"about.browsing_guest": "You are browsing as a guest.",
"about.back_home": "Back to Home",
"flash.post_published": "Post published successfully!",
"flash.post_saved_draft": "Post saved as draft!",
"flash.post_updated": "Post updated successfully!",
"flash.post_deleted": "Post deleted successfully!",
"flash.post_not_found": "Post not found.",
"base.close_message": "Close message",
"base.default_title": "Blog",
"base.meta_description": "Blog - A modern blogging platform built with FastAPI",
"base.meta_keywords": "blog, articles, posts, writing",
"base.meta_author": "Blog Team",
"lang.en": "English",
"lang.ru": "Русский",
"lang.fr": "Français",
"lang.de": "Deutsch",
},
"ru": {
"nav.home": "Главная",
"nav.posts": "Статьи",
"nav.about": "О нас",
"header.logo": "Блог",
"header.profile": "Профиль",
"header.new_post": "Новая статья",
"header.sign_out": "Выйти",
"header.sign_in": "Войти",
"header.toggle_menu": "Открыть меню",
"header.toggle_theme": "Сменить тему",
"header.lang_switcher": "Язык",
"footer.copyright": "© 2026 Блог. Все права защищены.",
"footer.about": "О нас",
"footer.privacy": "Конфиденциальность",
"footer.terms": "Условия",
"footer.api": "API",
"home.title": "Блог — Главная",
"home.meta_description": "Откройте для себя истории, мысли и опыт авторов на любую тему. Современный блог на FastAPI.",
"home.meta_keywords": "блог, статьи, посты, fastapi, python",
"home.page_title": "Последние статьи",
"home.page_subtitle": "Откройте для себя истории, мысли и опыт авторов на любую тему.",
"home.write_post": "Написать статью",
"home.status_published": "Опубликовано",
"home.status_draft": "Черновик",
"home.read_more": "Читать далее",
"home.pagination_previous": "Назад",
"home.pagination_next": "Вперёд",
"home.empty_title": "Статей пока нет",
"home.empty_description": "Будьте первым, кто напишет статью!",
"home.empty_action": "Создать первую статью",
"post.status_published": "Опубликовано",
"post.status_draft": "Черновик",
"post.back_to_posts": "К списку статей",
"post.edit": "Редактировать",
"post.delete": "Удалить",
"post.delete_confirm": "Вы уверены, что хотите удалить эту статью?",
"post_form.title_edit": "Редактировать статью",
"post_form.title_new": "Новая статья",
"post_form.page_title_edit": "Редактировать статью",
"post_form.page_title_new": "Создать новую статью",
"post_form.label_title": "Заголовок",
"post_form.placeholder_title": "Введите заголовок статьи",
"post_form.hint_title": "Запоминающийся заголовок для вашей статьи",
"post_form.label_content": "Содержание",
"post_form.placeholder_content": "Напишите содержание статьи здесь...",
"post_form.hint_content": "Основное содержание вашей статьи. Поддерживается Markdown.",
"post_form.label_tags": "Теги",
"post_form.placeholder_tags": "python, fastapi, tutorial",
"post_form.hint_tags": "Список тегов через запятую",
"post_form.cancel": "Отмена",
"post_form.save_draft": "Сохранить черновик",
"post_form.update_post": "Обновить статью",
"post_form.publish_post": "Опубликовать статью",
"profile.title": "Профиль пользователя",
"profile.email": "Email:",
"profile.not_provided": "Не указан",
"profile.user_id": "ID пользователя:",
"profile.name": "Имя:",
"profile.back_home": "На главную",
"profile.new_post": "Новая статья",
"about.title": "О нас",
"about.page_title": "О нас",
"about.description": "Современный блог на FastAPI с архитектурой Domain-Driven Design.",
"about.signed_in": "Вы вошли как {username}.",
"about.browsing_guest": "Вы просматриваете как гость.",
"about.back_home": "На главную",
"flash.post_published": "Статья успешно опубликована!",
"flash.post_saved_draft": "Статья сохранена как черновик!",
"flash.post_updated": "Статья успешно обновлена!",
"flash.post_deleted": "Статья успешно удалена!",
"flash.post_not_found": "Статья не найдена.",
"base.close_message": "Закрыть сообщение",
"base.default_title": "Блог",
"base.meta_description": "Блог — современная платформа для блогов на FastAPI",
"base.meta_keywords": "блог, статьи, посты, письмо",
"base.meta_author": "Команда блога",
"lang.en": "English",
"lang.ru": "Русский",
"lang.fr": "Français",
"lang.de": "Deutsch",
},
"fr": {
"nav.home": "Accueil",
"nav.posts": "Articles",
"nav.about": "À propos",
"header.logo": "Blog",
"header.profile": "Profil",
"header.new_post": "Nouvel article",
"header.sign_out": "Déconnexion",
"header.sign_in": "Connexion",
"header.toggle_menu": "Menu",
"header.toggle_theme": "Changer le thème",
"header.lang_switcher": "Langue",
"footer.copyright": "© 2026 Blog. Tous droits réservés.",
"footer.about": "À propos",
"footer.privacy": "Confidentialité",
"footer.terms": "Conditions",
"footer.api": "API",
"home.title": "Blog — Accueil",
"home.meta_description": "Découvrez des histoires, réflexions et expertises d'auteurs sur tous les sujets. Un blog moderne avec FastAPI.",
"home.meta_keywords": "blog, articles, posts, écriture, fastapi, python",
"home.page_title": "Derniers articles",
"home.page_subtitle": "Découvrez des histoires, réflexions et expertises d'auteurs sur tous les sujets.",
"home.write_post": "Écrire un article",
"home.status_published": "Publié",
"home.status_draft": "Brouillon",
"home.read_more": "Lire la suite",
"home.pagination_previous": "Précédent",
"home.pagination_next": "Suivant",
"home.empty_title": "Aucun article pour le moment",
"home.empty_description": "Soyez le premier à écrire un article !",
"home.empty_action": "Créer votre premier article",
"post.status_published": "Publié",
"post.status_draft": "Brouillon",
"post.back_to_posts": "Retour aux articles",
"post.edit": "Modifier",
"post.delete": "Supprimer",
"post.delete_confirm": "Êtes-vous sûr de vouloir supprimer cet article ?",
"post_form.title_edit": "Modifier l'article",
"post_form.title_new": "Nouvel article",
"post_form.page_title_edit": "Modifier l'article",
"post_form.page_title_new": "Créer un nouvel article",
"post_form.label_title": "Titre",
"post_form.placeholder_title": "Entrez le titre de l'article",
"post_form.hint_title": "Un titre accrocheur pour votre article",
"post_form.label_content": "Contenu",
"post_form.placeholder_content": "Écrivez votre article ici...",
"post_form.hint_content": "Le contenu principal de votre article. Markdown est supporté.",
"post_form.label_tags": "Tags",
"post_form.placeholder_tags": "python, fastapi, tutorial",
"post_form.hint_tags": "Liste de tags séparés par des virgules",
"post_form.cancel": "Annuler",
"post_form.save_draft": "Sauvegarder le brouillon",
"post_form.update_post": "Mettre à jour",
"post_form.publish_post": "Publier",
"profile.title": "Profil utilisateur",
"profile.email": "Email :",
"profile.not_provided": "Non fourni",
"profile.user_id": "ID utilisateur :",
"profile.name": "Nom :",
"profile.back_home": "Retour à l'accueil",
"profile.new_post": "Nouvel article",
"about.title": "À propos",
"about.page_title": "À propos",
"about.description": "Un blog moderne construit avec FastAPI et une architecture Domain-Driven Design.",
"about.signed_in": "Connecté en tant que {username}.",
"about.browsing_guest": "Vous naviguez en tant qu'invité.",
"about.back_home": "Retour à l'accueil",
"flash.post_published": "Article publié avec succès !",
"flash.post_saved_draft": "Article sauvegardé comme brouillon !",
"flash.post_updated": "Article mis à jour avec succès !",
"flash.post_deleted": "Article supprimé avec succès !",
"flash.post_not_found": "Article non trouvé.",
"base.close_message": "Fermer le message",
"base.default_title": "Blog",
"base.meta_description": "Blog — Une plateforme de blog moderne construite avec FastAPI",
"base.meta_keywords": "blog, articles, posts, écriture",
"base.meta_author": "Équipe du blog",
"lang.en": "English",
"lang.ru": "Русский",
"lang.fr": "Français",
"lang.de": "Deutsch",
},
"de": {
"nav.home": "Startseite",
"nav.posts": "Beiträge",
"nav.about": "Über uns",
"header.logo": "Blog",
"header.profile": "Profil",
"header.new_post": "Neuer Beitrag",
"header.sign_out": "Abmelden",
"header.sign_in": "Anmelden",
"header.toggle_menu": "Menü umschalten",
"header.toggle_theme": "Design umschalten",
"header.lang_switcher": "Sprache",
"footer.copyright": "© 2026 Blog. Alle Rechte vorbehalten.",
"footer.about": "Über uns",
"footer.privacy": "Datenschutz",
"footer.terms": "AGB",
"footer.api": "API",
"home.title": "Blog — Startseite",
"home.meta_description": "Entdecken Sie Geschichten, Gedanken und Fachwissen von Autoren zu jedem Thema. Ein moderner Blog mit FastAPI.",
"home.meta_keywords": "Blog, Artikel, Beiträge, Schreiben, Fastapi, Python",
"home.page_title": "Neueste Beiträge",
"home.page_subtitle": "Entdecken Sie Geschichten, Gedanken und Fachwissen von Autoren zu jedem Thema.",
"home.write_post": "Beitrag schreiben",
"home.status_published": "Veröffentlicht",
"home.status_draft": "Entwurf",
"home.read_more": "Weiterlesen",
"home.pagination_previous": "Zurück",
"home.pagination_next": "Weiter",
"home.empty_title": "Noch keine Beiträge",
"home.empty_description": "Schreiben Sie den ersten Beitrag!",
"home.empty_action": "Ersten Beitrag erstellen",
"post.status_published": "Veröffentlicht",
"post.status_draft": "Entwurf",
"post.back_to_posts": "Zurück zu den Beiträgen",
"post.edit": "Bearbeiten",
"post.delete": "Löschen",
"post.delete_confirm": "Sind Sie sicher, dass Sie diesen Beitrag löschen möchten?",
"post_form.title_edit": "Beitrag bearbeiten",
"post_form.title_new": "Neuer Beitrag",
"post_form.page_title_edit": "Beitrag bearbeiten",
"post_form.page_title_new": "Neuen Beitrag erstellen",
"post_form.label_title": "Titel",
"post_form.placeholder_title": "Geben Sie den Beitragstitel ein",
"post_form.hint_title": "Ein eingängiger Titel für Ihren Beitrag",
"post_form.label_content": "Inhalt",
"post_form.placeholder_content": "Schreiben Sie Ihren Beitrag hier...",
"post_form.hint_content": "Der Hauptinhalt Ihres Beitrags. Markdown wird unterstützt.",
"post_form.label_tags": "Tags",
"post_form.placeholder_tags": "python, fastapi, tutorial",
"post_form.hint_tags": "Kommagetrennte Tag-Liste",
"post_form.cancel": "Abbrechen",
"post_form.save_draft": "Als Entwurf speichern",
"post_form.update_post": "Beitrag aktualisieren",
"post_form.publish_post": "Beitrag veröffentlichen",
"profile.title": "Benutzerprofil",
"profile.email": "E-Mail:",
"profile.not_provided": "Nicht angegeben",
"profile.user_id": "Benutzer-ID:",
"profile.name": "Name:",
"profile.back_home": "Zurück zur Startseite",
"profile.new_post": "Neuer Beitrag",
"about.title": "Über uns",
"about.page_title": "Über uns",
"about.description": "Ein moderner Blog, erstellt mit FastAPI und Domain-Driven Design Architektur.",
"about.signed_in": "Angemeldet als {username}.",
"about.browsing_guest": "Sie surfen als Gast.",
"about.back_home": "Zurück zur Startseite",
"flash.post_published": "Beitrag erfolgreich veröffentlicht!",
"flash.post_saved_draft": "Beitrag als Entwurf gespeichert!",
"flash.post_updated": "Beitrag erfolgreich aktualisiert!",
"flash.post_deleted": "Beitrag erfolgreich gelöscht!",
"flash.post_not_found": "Beitrag nicht gefunden.",
"base.close_message": "Nachricht schließen",
"base.default_title": "Blog",
"base.meta_description": "Blog — Eine moderne Blogging-Plattform mit FastAPI",
"base.meta_keywords": "Blog, Artikel, Beiträge, Schreiben",
"base.meta_author": "Blog-Team",
"lang.en": "English",
"lang.ru": "Русский",
"lang.fr": "Français",
"lang.de": "Deutsch",
},
}