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