mirror of
https://github.com/Hopiu/django-rosetta.git
synced 2026-03-16 21:30:24 +00:00
202 lines
6.5 KiB
Python
202 lines
6.5 KiB
Python
import os
|
|
import tempfile
|
|
from datetime import datetime
|
|
|
|
import django
|
|
from django.apps import apps
|
|
from django.conf import ENVIRONMENT_VARIABLE, settings
|
|
from django.core.cache import caches
|
|
from django.utils import timezone
|
|
|
|
from rosetta.conf import settings as rosetta_settings
|
|
|
|
|
|
cache = caches[rosetta_settings.ROSETTA_CACHE_NAME]
|
|
|
|
|
|
def timestamp_with_timezone(dt=None):
|
|
"""
|
|
Return a timestamp with a timezone for the configured locale. If all else
|
|
fails, consider localtime to be UTC.
|
|
"""
|
|
dt = dt or datetime.now()
|
|
if timezone is None:
|
|
return dt.strftime("%Y-%m-%d %H:%M%z")
|
|
if not dt.tzinfo:
|
|
tz = timezone.get_current_timezone()
|
|
if not tz:
|
|
tz = timezone.utc
|
|
dt = dt.replace(tzinfo=timezone.get_current_timezone())
|
|
return dt.strftime("%Y-%m-%d %H:%M%z")
|
|
|
|
|
|
def find_pos(lang, project_apps=True, django_apps=False, third_party_apps=False):
|
|
"""
|
|
scans a couple possible repositories of gettext catalogs for the given
|
|
language code
|
|
|
|
"""
|
|
|
|
paths = []
|
|
|
|
# project/locale
|
|
if settings.SETTINGS_MODULE:
|
|
parts = settings.SETTINGS_MODULE.split(".")
|
|
else:
|
|
# if settings.SETTINGS_MODULE is None, we are probably in "test" mode
|
|
# and override_settings() was used
|
|
# see: https://code.djangoproject.com/ticket/25911
|
|
parts = os.environ.get(ENVIRONMENT_VARIABLE).split(".")
|
|
project = __import__(parts[0], {}, {}, [])
|
|
abs_project_path = os.path.normpath(
|
|
os.path.abspath(os.path.dirname(project.__file__))
|
|
)
|
|
if project_apps:
|
|
if os.path.exists(
|
|
os.path.abspath(os.path.join(os.path.dirname(project.__file__), "locale"))
|
|
):
|
|
paths.append(
|
|
os.path.abspath(
|
|
os.path.join(os.path.dirname(project.__file__), "locale")
|
|
)
|
|
)
|
|
if os.path.exists(
|
|
os.path.abspath(
|
|
os.path.join(os.path.dirname(project.__file__), "..", "locale")
|
|
)
|
|
):
|
|
paths.append(
|
|
os.path.abspath(
|
|
os.path.join(os.path.dirname(project.__file__), "..", "locale")
|
|
)
|
|
)
|
|
|
|
# is OS case sensitive? settings preferred over auto detection
|
|
case_sensitive_file_system = getattr(
|
|
settings, "ROSETTA_CASE_SENSITIVE_FILESYSTEM", None
|
|
)
|
|
|
|
# in case of no settings, attempt auto detection
|
|
if case_sensitive_file_system is None:
|
|
case_sensitive_file_system = True
|
|
tmphandle, tmppath = tempfile.mkstemp()
|
|
if os.path.exists(tmppath.upper()):
|
|
# Case insensitive file system.
|
|
case_sensitive_file_system = False
|
|
|
|
# django/locale
|
|
if django_apps:
|
|
django_paths = cache.get("rosetta_django_paths")
|
|
if django_paths is None:
|
|
django_paths = []
|
|
for root, dirnames, filename in os.walk(
|
|
os.path.abspath(os.path.dirname(django.__file__))
|
|
):
|
|
if "locale" in dirnames:
|
|
django_paths.append(os.path.join(root, "locale"))
|
|
continue
|
|
cache.set("rosetta_django_paths", django_paths, 60 * 60)
|
|
paths = paths + django_paths
|
|
# settings
|
|
for localepath in settings.LOCALE_PATHS:
|
|
if os.path.isdir(localepath):
|
|
paths.append(localepath)
|
|
|
|
# project/app/locale
|
|
for app_ in apps.get_app_configs():
|
|
if (
|
|
rosetta_settings.EXCLUDED_APPLICATIONS
|
|
and app_.name in rosetta_settings.EXCLUDED_APPLICATIONS
|
|
):
|
|
continue
|
|
|
|
app_path = app_.path
|
|
# django apps
|
|
if "contrib" in app_path and "django" in app_path and not django_apps:
|
|
continue
|
|
|
|
# third party external
|
|
if not third_party_apps and abs_project_path not in app_path:
|
|
continue
|
|
|
|
# local apps
|
|
if not project_apps and abs_project_path in app_path:
|
|
continue
|
|
|
|
if os.path.exists(os.path.abspath(os.path.join(app_path, "locale"))):
|
|
paths.append(os.path.abspath(os.path.join(app_path, "locale")))
|
|
if os.path.exists(os.path.abspath(os.path.join(app_path, "..", "locale"))):
|
|
paths.append(os.path.abspath(os.path.join(app_path, "..", "locale")))
|
|
|
|
ret = set()
|
|
langs = [lang]
|
|
if "-" in lang:
|
|
_l, _c = map(lambda x: x.lower(), lang.split("-", 1))
|
|
langs += [
|
|
"%s_%s" % (_l, _c),
|
|
"%s_%s" % (_l, _c.upper()),
|
|
"%s_%s" % (_l, _c.capitalize()),
|
|
]
|
|
elif "_" in lang:
|
|
_l, _c = map(lambda x: x.lower(), lang.split("_", 1))
|
|
langs += [
|
|
"%s-%s" % (_l, _c),
|
|
"%s-%s" % (_l, _c.upper()),
|
|
"%s_%s" % (_l, _c.capitalize()),
|
|
]
|
|
|
|
paths = map(os.path.normpath, paths)
|
|
paths = list(set(paths))
|
|
for path in paths:
|
|
# Exclude paths
|
|
if path not in rosetta_settings.ROSETTA_EXCLUDED_PATHS:
|
|
for lang_ in langs:
|
|
dirname = os.path.join(path, lang_, "LC_MESSAGES")
|
|
for fn in rosetta_settings.POFILENAMES:
|
|
filename = os.path.join(dirname, fn)
|
|
abs_path = os.path.abspath(filename)
|
|
# On case insensitive filesystems (looking at you, MacOS)
|
|
# compare the lowercase absolute path of the po file
|
|
# to all lowercased paths already collected.
|
|
# This is not an issue on sane filesystems
|
|
if not case_sensitive_file_system:
|
|
if filename.lower() in [p.lower() for p in ret]:
|
|
continue
|
|
if os.path.isfile(abs_path):
|
|
ret.add(abs_path)
|
|
return list(sorted(ret))
|
|
|
|
|
|
def pagination_range(first, last, current):
|
|
r = []
|
|
|
|
r.append(first)
|
|
if first + 1 < last:
|
|
r.append(first + 1)
|
|
|
|
if current - 2 > first and current - 2 < last:
|
|
r.append(current - 2)
|
|
if current - 1 > first and current - 1 < last:
|
|
r.append(current - 1)
|
|
if current > first and current < last:
|
|
r.append(current)
|
|
if current + 1 < last and current + 1 > first:
|
|
r.append(current + 1)
|
|
if current + 2 < last and current + 2 > first:
|
|
r.append(current + 2)
|
|
|
|
if last - 1 > first:
|
|
r.append(last - 1)
|
|
r.append(last)
|
|
|
|
r = list(set(r))
|
|
r.sort()
|
|
prev = 10000
|
|
for e in r[:]:
|
|
if prev + 1 < e:
|
|
try:
|
|
r.insert(r.index(e), "...")
|
|
except ValueError:
|
|
pass
|
|
prev = e
|
|
return r
|