diff --git a/config/settings.py b/config/settings.py
index 1bbd576..0f93c69 100644
--- a/config/settings.py
+++ b/config/settings.py
@@ -1,5 +1,7 @@
from pathlib import Path
+from django.utils.translation import gettext_lazy as _
+
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
@@ -13,6 +15,24 @@ ALLOWED_HOSTS = []
INTERNAL_IPS = ['localhost', '127.0.0.1',]
+#
+
+LANGUAGES = [
+ ('en', _('English')),
+ ('fi', _('Finnish')),
+]
+
+LANGUAGE_CODE = 'en'
+
+USE_I18N = True
+USE_L10N = True
+USE_TZ = True
+
+LOCALE_PATHS = [
+ BASE_DIR / 'locale',
+]
+
+
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
@@ -30,6 +50,7 @@ INSTALLED_APPS = [
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.middleware.locale.LocaleMiddleware', # Locale
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
diff --git a/config/urls.py b/config/urls.py
index 84cde86..b613125 100644
--- a/config/urls.py
+++ b/config/urls.py
@@ -1,4 +1,5 @@
from django.conf import settings
+from django.conf.urls.i18n import i18n_patterns
from django.conf.urls.static import static
from django.contrib import admin
from django.contrib.sitemaps.views import sitemap
@@ -15,14 +16,10 @@ urlpatterns = [
path("sitemap.xml", sitemap, {'sitemaps': sitemaps}, name='django.contrib.sitemaps.views.sitemap'),
path('admin/', admin.site.urls),
path('favicon.ico/', RedirectView.as_view(url='/static/favicon.ico', permanent=True)),
+ path('i18n/', include('django.conf.urls.i18n')),
path('', include(('gallery.urls', 'gallery'), namespace='gallery')),
]
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
-
-
-
-
-
diff --git a/gallery/templates/gallery/about.html b/gallery/templates/gallery/about.html
index 1af3adf..2134bb9 100644
--- a/gallery/templates/gallery/about.html
+++ b/gallery/templates/gallery/about.html
@@ -1,9 +1,10 @@
{% extends "base.html" %}
{% load static %}
+{% load i18n %}
{% load gallery_stats %}
-{% block title %} About {% endblock %}
+{% block title %} {% trans "About" %} {% endblock %}
{% block parallax %}
@@ -16,8 +17,8 @@
-
Muistox gallery
+
{% trans "Muistox gallery" %}
- Just another wannabe photographer...
+ {% trans "Just another wannabe photographer..." %}
- {{ counts.0 }} Albums (public {{ counts.1 }}),
- {{ counts.2 }} Photos
+
{{ counts.0 }}
+
+ {% blocktrans count album_count=counts.0 %}album{% plural %}albums{% endblocktrans %}
+
+ ( {% blocktrans count public_count=counts.1 %}{{ public_count }} public{% plural %}{{ public_count }} public{% endblocktrans %} )
+
{{ counts.2 }}
+
+ {% blocktrans count photo_count=counts.2 %}photo{% plural %}photos{% endblocktrans %}
+
+
diff --git a/gallery/templates/gallery/album_detail.html b/gallery/templates/gallery/album_detail.html
index 23b9dfd..a4900ae 100644
--- a/gallery/templates/gallery/album_detail.html
+++ b/gallery/templates/gallery/album_detail.html
@@ -1,6 +1,6 @@
{% extends "base.html" %}
{% load static %}
-
+{% load i18n %}
{% block title %} {{ album.name }} {% endblock %}
@@ -32,32 +32,15 @@
{% for photo in photos %}
-
-
-
+ {% include "gallery/partials/photo_thumbnail.html" with photo=photo %}
{% endfor %}
diff --git a/gallery/templates/gallery/album_list.html b/gallery/templates/gallery/album_list.html
index 40d6655..389b7aa 100644
--- a/gallery/templates/gallery/album_list.html
+++ b/gallery/templates/gallery/album_list.html
@@ -1,9 +1,9 @@
{% extends "base.html" %}
{% load static %}
-{% load image_tags %}
+{% load i18n %}
-{% block title %} Albums {% endblock %}
+{% block title %} {% trans "Albums" %} {% endblock %}
{% block parallax %}
@@ -16,50 +16,15 @@
{% for album in album_list %}
-
-
-
-
-
-
-
-
-
-
- {{ album.photos_in_album }} photos •
- {{ album.photos_views }} views
-
-
-
-
-
+ {% include "gallery/partials/album_card.html" %}
{% endfor %}
diff --git a/gallery/templates/gallery/album_search.html b/gallery/templates/gallery/album_search.html
index fd13000..e55fe4b 100644
--- a/gallery/templates/gallery/album_search.html
+++ b/gallery/templates/gallery/album_search.html
@@ -1,9 +1,10 @@
{% extends "base.html" %}
{% load static %}
+{% load i18n %}
{% load image_tags %}
-{% block title %} Search {% endblock %}
+{% block title %} {% trans "Search" %} {% endblock %}
{% block parallax %}
@@ -16,8 +17,8 @@
@@ -25,42 +26,7 @@
{% if results %}
{% for album in results %}
-
-
-
-
-
-
-
-
-
-
- {{ album.photos_in_album }} photos •
- {{ album.photos_views }} views
-
-
-
-
-
+ {% include "gallery/partials/album_card.html" %}
{% endfor %}
{% else %}
Not found: "{{ query }}".
diff --git a/gallery/templates/gallery/main.html b/gallery/templates/gallery/main.html
index b6bbcfa..3373150 100644
--- a/gallery/templates/gallery/main.html
+++ b/gallery/templates/gallery/main.html
@@ -1,9 +1,9 @@
{% extends "base.html" %}
{% load static %}
-{% load image_tags %}
+{% load i18n %}
-{% block title %}Home{% endblock %}
+{% block title %} {% trans "Home" %} {% endblock %}
{% block parallax %}
@@ -13,100 +13,27 @@
{% block content %}
-
{% load top_tags %}
- {% load image_tags %}
+
+
{% random_favorite_photos_portrait 10 as top_portrait_photos %}
-
{% if top_portrait_photos %}
-
-
-
- {% for photo in top_portrait_photos %}
- {% with photo|photo_image_data as data %}
-
- {% endwith %}
- {% endfor %}
-
-
-
-
-
-
+ {% include "gallery/partials/photos_slider.html" with photos=top_portrait_photos %}
{% endif %}
-
+
{% for album in latest_albums %}
-
-
-
-
-
-
-
-
-
-
- {{ album.photos_in_album }} photos •
- {{ album.photos_views }} views
-
-
-
-
-
+ {% include "gallery/partials/album_card.html" %}
{% endfor %}
- {% load top_tags %}
- {% load image_tags %}
{% random_favorite_photos_landscape 10 as top_landscape_photos %}
-
{% if top_landscape_photos %}
-
-
-
- {% for photo in top_landscape_photos %}
- {% with photo|photo_image_data as data %}
-
- {% endwith %}
- {% endfor %}
-
-
-
-
-
-
+ {% include "gallery/partials/photos_slider.html" with photos=top_landscape_photos %}
{% endif %}
{% endblock %}
\ No newline at end of file
diff --git a/gallery/templates/gallery/partials/album_card.html b/gallery/templates/gallery/partials/album_card.html
new file mode 100644
index 0000000..9247668
--- /dev/null
+++ b/gallery/templates/gallery/partials/album_card.html
@@ -0,0 +1,39 @@
+{% load image_tags %}
+{% load i18n %}
+
+
+
+
+
+
+
+
+
+
+ {% blocktrans count photo_count=album.photos_in_album %}{{ photo_count }} photo{% plural %}{{ photo_count }} photos{% endblocktrans %}
+ •
+ {% blocktrans count view_count=album.photos_views %}{{ view_count }} view{% plural %}{{ view_count }} views{% endblocktrans %}
+
+
+
+
+
\ No newline at end of file
diff --git a/gallery/templates/gallery/partials/pagination.html b/gallery/templates/gallery/partials/pagination.html
index 69b7f33..354cafc 100644
--- a/gallery/templates/gallery/partials/pagination.html
+++ b/gallery/templates/gallery/partials/pagination.html
@@ -1,3 +1,4 @@
+{% load i18n %}
{% load link_tags %}
{% if page_obj.has_other_pages %}
@@ -6,9 +7,9 @@
diff --git a/gallery/templates/gallery/partials/parallax.html b/gallery/templates/gallery/partials/parallax.html
index 6074ed4..7386b4d 100644
--- a/gallery/templates/gallery/partials/parallax.html
+++ b/gallery/templates/gallery/partials/parallax.html
@@ -1,5 +1,6 @@
{% load top_tags %}
{% load static %}
+{% load i18n %}
@@ -36,9 +37,9 @@
-
Gallery
+ {% trans "Gallery" %}
-
Just another wannabe photographer...
+
{% trans "Just another wannabe photographer..." %}
\ No newline at end of file
diff --git a/gallery/templates/gallery/partials/photo_thumbnail.html b/gallery/templates/gallery/partials/photo_thumbnail.html
new file mode 100644
index 0000000..88e8c39
--- /dev/null
+++ b/gallery/templates/gallery/partials/photo_thumbnail.html
@@ -0,0 +1,18 @@
+
+
+
\ No newline at end of file
diff --git a/gallery/templates/gallery/partials/photos_slider.html b/gallery/templates/gallery/partials/photos_slider.html
new file mode 100644
index 0000000..36dd787
--- /dev/null
+++ b/gallery/templates/gallery/partials/photos_slider.html
@@ -0,0 +1,20 @@
+{% load image_tags %}
+
+
+
+
+ {% for photo in photos %}
+ {% with photo|photo_image_data as data %}
+
+ {% endwith %}
+ {% endfor %}
+
+
+
+
+
+
diff --git a/gallery/templates/gallery/photo_detail.html b/gallery/templates/gallery/photo_detail.html
index cb1dd47..fe618a1 100644
--- a/gallery/templates/gallery/photo_detail.html
+++ b/gallery/templates/gallery/photo_detail.html
@@ -1,4 +1,5 @@
{% extends "base.html" %}
+{% load i18n %}
{% load exif_filters %}
@@ -47,8 +48,8 @@
@@ -60,38 +61,38 @@
-
Photo Info
+
{% trans "Photo Info" %}
-
Album name
+
{% trans "Album" %}
-
Photo id
+
{% trans "Photo Name" %}
-
Photo Taken
+
{% trans "Photo Taken" %}
{{ photo.taken_at|date:"d.m.Y H:i" }}
-
Views
+
{% trans "Views" %}
{{ photo.views }}
-
Likes
+
{% trans "Likes" %}
{{ photo.likes }}
@@ -100,37 +101,37 @@
-
Exif
+
{% trans "Exif" %}
-
Camera
+
{% trans "Camera" %}
{{ photo.exif.Model }}
-
Lens
+
{% trans "Lens" %}
{{ photo.exif.LensModel }}
-
Shutter Speed
+
{% trans "Shutter Speed" %}
{{ photo.exif.ExposureTime|exif_exposuretime }}
-
Aperture
+
{% trans "Aperture" %}
{{ photo.exif.FNumber|exif_fnumber }}
-
ISO
+
{% trans "ISO" %}
{{ photo.exif.ISOSpeedRatings|exif_isospeedratings }}
-
Focal Length
+
{% trans "Focal Length" %}
{{ photo.exif.FocalLength|exif_focallength}}
-
Focal Length in 35mm
+
{% trans "Focal Length in 35mm" %}
{{ photo.exif.FocalLengthIn35mmFilm|exif_focallength }}
-
Keywords
+
{% trans "Keywords" %}
{{ photo.exif.Keywords|exif_keywords }}
diff --git a/gallery/templates/gallery/photo_list.html b/gallery/templates/gallery/photo_list.html
index fcc22eb..03cdcde 100644
--- a/gallery/templates/gallery/photo_list.html
+++ b/gallery/templates/gallery/photo_list.html
@@ -1,8 +1,9 @@
{% extends "base.html" %}
{% load static %}
+{% load i18n %}
-{% block title %} Photostream {% endblock %}
+{% block title %} {% trans "Photostream" %} {% endblock %}
{% block parallax %}
@@ -18,46 +19,28 @@
-
{% for photo in object_list %}
-
-
-
+ {% include "gallery/partials/photo_thumbnail.html" with photo=photo %}
{% endfor %}
diff --git a/gallery/templates/gallery/photo_slideshow.html b/gallery/templates/gallery/photo_slideshow.html
index 9e643d9..b967909 100644
--- a/gallery/templates/gallery/photo_slideshow.html
+++ b/gallery/templates/gallery/photo_slideshow.html
@@ -2,10 +2,11 @@
{% load static %}
+ {% load i18n %}
-
-
Slideshow : {{ photo.album.name }} - Gallery
+
+
{% trans "Slideshow" %} : {{ photo.album.name }} - {% trans "Gallery" %}
{% if next_photo %}
{% endif %}
diff --git a/locale/en/LC_MESSAGES/django.po b/locale/en/LC_MESSAGES/django.po
new file mode 100644
index 0000000..87477c7
--- /dev/null
+++ b/locale/en/LC_MESSAGES/django.po
@@ -0,0 +1,149 @@
+# Muistox galleria – en käännökset.
+# Copyright (C) 2025 Nyymix
+# This file is distributed under the same license as the muistox package.
+# Nyymix
, 2025.
+#
+msgid ""
+msgstr ""
+"Language: en\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+
+msgid "Gallery"
+msgstr ""
+
+msgid "Home"
+msgstr ""
+
+msgid "Albums"
+msgstr ""
+
+msgid "Photostream"
+msgstr ""
+
+msgid "About"
+msgstr ""
+
+msgid "Admin"
+msgstr ""
+
+msgid "Search"
+msgstr ""
+
+msgid "Slideshow"
+msgstr ""
+
+msgid "Muistox Photo Gallery"
+msgstr ""
+
+msgid "Search albums"
+msgstr ""
+
+msgid "Latest"
+msgstr ""
+
+msgid "Liked"
+msgstr ""
+
+msgid "Popular"
+msgstr ""
+
+msgid "%(photo_count)s photo"
+msgid_plural "%(photo_count)s photos"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%(view_count)s view"
+msgid_plural "%(view_count)s views"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Photo Info"
+msgstr ""
+
+msgid "Album"
+msgstr ""
+
+msgid "Photo Name"
+msgstr ""
+
+msgid "Photo Taken"
+msgstr ""
+
+msgid "Views"
+msgstr ""
+
+msgid "Likes"
+msgstr ""
+
+msgid "Download"
+msgstr ""
+
+msgid "Like"
+msgstr ""
+
+msgid "Exif"
+msgstr ""
+
+msgid "Camera"
+msgstr ""
+
+msgid "Lens"
+msgstr ""
+
+msgid "Shutter Speed"
+msgstr ""
+
+msgid "Aperture"
+msgstr ""
+
+msgid "ISO"
+msgstr ""
+
+msgid "Focal Length"
+msgstr ""
+
+msgid "Focal Length in 35mm"
+msgstr ""
+
+msgid "Keywords"
+msgstr ""
+
+msgid "Prev"
+msgstr ""
+
+msgid "Next"
+msgstr ""
+
+msgid "%(public_count)s public"
+msgid_plural "%(public_count)s public"
+msgstr[0] "%(public_count)s public"
+msgstr[1] "%(public_count)s public"
+
+msgid "album"
+msgid_plural "albums"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "photo"
+msgid_plural "photos"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Contact"
+msgstr ""
+
+msgid "Muistox gallery"
+msgstr ""
+
+msgid "Just another wannabe photographer..."
+msgstr ""
+
+msgid "Events photography"
+msgstr ""
+
+msgid "Nyymix.net Gallery"
+msgstr ""
\ No newline at end of file
diff --git a/locale/fi/LC_MESSAGES/django.po b/locale/fi/LC_MESSAGES/django.po
new file mode 100644
index 0000000..8b69408
--- /dev/null
+++ b/locale/fi/LC_MESSAGES/django.po
@@ -0,0 +1,149 @@
+# Muistox galleria – fi käännökset.
+# Copyright (C) 2025 Nyymix
+# This file is distributed under the same license as the muistox package.
+# Nyymix , 2025.
+#
+msgid ""
+msgstr ""
+"Language: fi\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+
+msgid "Gallery"
+msgstr "Galleria"
+
+msgid "Home"
+msgstr "Etusivu"
+
+msgid "Albums"
+msgstr "Albumit"
+
+msgid "Photostream"
+msgstr "Valokuvat"
+
+msgid "About"
+msgstr "Tietoja"
+
+msgid "Admin"
+msgstr "Ylläpito"
+
+msgid "Search"
+msgstr "Haku"
+
+msgid "Slideshow"
+msgstr "Diaesitys"
+
+msgid "Muistox Photo Gallery"
+msgstr "Muistox kuvagalleria"
+
+msgid "Search albums"
+msgstr "Hae albumeita"
+
+msgid "Latest"
+msgstr "Uusimmat"
+
+msgid "Liked"
+msgstr "Tykätyimmät"
+
+msgid "Popular"
+msgstr "Katsotuimmat"
+
+msgid "%(photo_count)s photo"
+msgid_plural "%(photo_count)s photos"
+msgstr[0] "%(photo_count)s kuva"
+msgstr[1] "%(photo_count)s kuvaa"
+
+msgid "%(view_count)s view"
+msgid_plural "%(view_count)s views"
+msgstr[0] "%(view_count)s näyttökerta"
+msgstr[1] "%(view_count)s näyttökertaa"
+
+msgid "Photo Info"
+msgstr "Valokuvan tiedot"
+
+msgid "Album"
+msgstr "Albumi"
+
+msgid "Photo Name"
+msgstr "Valokuvan nimi"
+
+msgid "Photo Taken"
+msgstr "Valokuva otettu"
+
+msgid "Views"
+msgstr "Katselukerrat"
+
+msgid "Likes"
+msgstr "Tykkäykset"
+
+msgid "Download"
+msgstr "Lataa"
+
+msgid "Like"
+msgstr "Tykkää"
+
+msgid "Exif"
+msgstr "Exif"
+
+msgid "Camera"
+msgstr "Kamera"
+
+msgid "Lens"
+msgstr "Linssi"
+
+msgid "Shutter Speed"
+msgstr "Suljinaika"
+
+msgid "Aperture"
+msgstr "Aukko"
+
+msgid "ISO"
+msgstr "ISO"
+
+msgid "Focal Length"
+msgstr "Polttoväli"
+
+msgid "Focal Length in 35mm"
+msgstr "Polttoväli (35 mm kinovastaavuus)"
+
+msgid "Keywords"
+msgstr "Avainsanat"
+
+msgid "Prev"
+msgstr "Edellinen"
+
+msgid "Next"
+msgstr "Seuraava"
+
+msgid "%(public_count)s public"
+msgid_plural "%(public_count)s public"
+msgstr[0] "%(public_count)s julkinen"
+msgstr[1] "%(public_count)s julkista"
+
+msgid "album"
+msgid_plural "albums"
+msgstr[0] "albumi"
+msgstr[1] "albumia"
+
+msgid "photo"
+msgid_plural "photos"
+msgstr[0] "kuva"
+msgstr[1] "kuvaa"
+
+msgid "Contact"
+msgstr "Ota yhteyttä"
+
+msgid "Muistox gallery"
+msgstr "Muistox Kuvagalleria"
+
+msgid "Just another wannabe photographer..."
+msgstr "Taas yksi, joka luulee olevansa valokuvaaja..."
+
+msgid "Events photography"
+msgstr "Tapahtumavalokuvausta"
+
+msgid "Nyymix.net Gallery"
+msgstr "Nyymix.net Kuvagalleria"
\ No newline at end of file
diff --git a/templates/base.html b/templates/base.html
index 73b2379..2a45486 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -3,6 +3,7 @@
{% load static %}
+ {% load i18n %}
@@ -32,21 +33,21 @@