Some checks failed
ci/woodpecker/pr/pipeline Pipeline failed
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
338 lines
18 KiB
Python
338 lines
18 KiB
Python
"""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",
|
||
},
|
||
}
|