diff --git a/.bumpversion.toml b/.bumpversion.toml new file mode 100755 index 000000000..f5f14423c --- /dev/null +++ b/.bumpversion.toml @@ -0,0 +1,35 @@ +[tool.bumpversion] +current_version = "3.4.4+pbs.1" +commit = false +tag = false +parse = """(?x) + (?P0|[1-9]\\d*)\\. + (?P0|[1-9]\\d*)\\. + (?P0|[1-9]\\d*) + \\+pbs\\. + (?P0|[1-9]\\d*) + (?: + \\.(?Pdev) + \\.g[0-9a-f]{7,40} + \\.\\d{8} + )? +""" + +serialize = [ + "{major}.{minor}.{patch}+pbs.{pbs}.{prekind}.g{$GITHUB_SHA}.{now:%Y%m%d}", + "{major}.{minor}.{patch}+pbs.{pbs}" +] + + +[tool.bumpversion.parts.prekind] +values = [ + "", + "dev" +] +optional_value = "" + + +[[tool.bumpversion.files]] +filename = "filer/__init__.py" +search = "{current_version}" +replace = "{new_version}" diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..d5481b3df --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,5 @@ +# The bento-dev-team is responsible for the whole repo +# * - all files +# pbs - org +# bento-dev-team - team +* @pbs/bento-dev-team diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 000000000..34a6a23a4 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,44 @@ +name: Tests + +on: + workflow_call: + pull_request: + branches: [ "**" ] + +jobs: + test: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.12", "3.13"] + + steps: + - uses: actions/checkout@v6 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v6 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pytest pytest-django "Django>=5.1,<5.2" + pip install -e . + + - name: Run tests + run: | + pytest \ + --junitxml=pytest-results.xml \ + --ds=filer.test_settings \ + --pyargs \ + filer.tests + + - name: Upload test results + if: always() + uses: actions/upload-artifact@v7 + with: + name: test-results-py${{ matrix.python-version }} + path: pytest-results.xml + diff --git a/.gitignore b/.gitignore index 157d67be8..4e08979de 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,10 @@ *.pyc +*.bak *.pyo .installed.cfg bin develop-eggs -dist +/dist downloads eggs parts @@ -12,6 +13,8 @@ tmp *.egg-info *.egg .DS_Store +.sass-cache +node_modules .project .pydevproject .settings @@ -27,3 +30,8 @@ pep8.txt htmlcov/ share/ .idea +*.iml +.tox +*.pyo +full.log +pytest-results.xml \ No newline at end of file diff --git a/CHANGELOG.rst b/CHANGELOG.rst new file mode 100644 index 000000000..6fbd0813b --- /dev/null +++ b/CHANGELOG.rst @@ -0,0 +1,438 @@ +CHANGELOG +========= + +Revision 6af1333 (15.05.2018, 12:39 UTC) +---------------------------------------- + +No new issues. + +* Misc commits + + * BEN-434: Add second trucate filename test. + * BEN-434: Add filename truncate test. + * BEN-434: Use filename with extesion instead of title. + +Revision e86cfa2 (08.08.2017, 15:01 UTC) +---------------------------------------- + +* LUN-3798 + + * Implement review findings + * Add unit-tests and bump version + * No 500 error at uploading long filename + +No other commits. + +Revision 108e8d0 (20.06.2017, 07:59 UTC) +---------------------------------------- + +* LUN-3517 + + * Put error messages in a dictionary + * removed commented code + * update unit-tests for clipboardadmin after changes + * do not show popup when same file uploaded + * fix detection of duplicate files + +No other commits. + +Revision f62676c (14.02.2017, 12:16 UTC) +---------------------------------------- + +* LUN-3465 + + * Allow positional parameters. + +* LUN-3545 + + * Add exlude name hashing rules for rootfolders. + +No other commits. + +Revision df5e50f (18.10.2016, 07:43 UTC) +---------------------------------------- + +* LUN-3289 + + * Rework permission checking to work with multiple managers. + +No other commits. + +Revision b5b4b34 (10.10.2016, 08:26 UTC) +---------------------------------------- + +No new issues. + +* Misc commits + + * Handle unicode in filemodels. + +Revision 23058b6 (29.09.2016, 12:07 UTC) +---------------------------------------- + +* LUN-3217 + + * Add option to filter files by type. + +* LUN-3221 + + * Set specific exceptions for sha1 generation. + * Review fixes. + * Add content hash to filenames so CDN urls are automatically invalidated. + +No other commits. + +Revision b0041d1 (06.09.2016, 08:55 UTC) +---------------------------------------- + +* LUN-3211 + + * add filer popup callback support for iframes + +No other commits. + +Revision 7095511 (15.06.2016, 14:37 UTC) +---------------------------------------- + +* LUN-2784 + + * Be graceful about base_fields lookup. + * Remove FolderAdmin related field actions + +No other commits. + +Revision e0c4870 (06.05.2016, 15:22 UTC) +---------------------------------------- + +* LUN-2622 + + * LUN-2960: Apply styling from LUN-2622 to trash change list view. + +* LUN-2960 + + * Apply styling from LUN-2622 to trash change list view. + +No other commits. + +Revision 9084219 (13.04.2016, 10:56 UTC) +---------------------------------------- + +* LUN-2961 + + * js-hint. + * Fix property name. + +No other commits. + +Revision 8611055 (01.04.2016, 07:22 UTC) +---------------------------------------- + +* LUN-2853 + + * PEP8 + * Remove deprecated request.REQUEST. + * Redirect files/folder '_save' changes to parent directory. + * Always redirect popup POST change requests to parent view. + +* LUN-2940 + + * Add unique constraint for user-clipboard. + * Whitespace. + +* Misc commits + + * Fix test. + +Revision 8776bb3 (03.02.2016, 07:35 UTC) +---------------------------------------- + +* LUN-2622 + + * Fix indenting. + * Fix search pop-up header margins. + * Fix filer search pop-up for minimum resolution. + +No other commits. + +Revision 3f84a76 (14.01.2016, 14:46 UTC) +---------------------------------------- + +* LUN-2689 + + * Handle case when request body is missing. + +* Misc commits + + * master_pbs Pin django-mptt to last working version. + +Revision 8cd8cf3 (18.11.2015, 08:15 UTC) +---------------------------------------- + +* LUN-2744 + + * Review: Refactored code that should be dead. Kept because not sure of intention. + * Review: identation & remove global variables. + * Review: Handle invalid urls. + * Add marker css class to show if a image is selected or not. + * Use full image size when widget is customized. + * Fix bug with file link not changing. + * Reworked customizable file widget to have a separate template. + * Refactored templates to separate custom image widget preview. + * custom preview- buttons updated + * Use widget customization for default case. + * Add option in file widget to enlarge preview and customize labels. + +* Misc commits + + * fixed misspelling from js file + +Revision 47a0d53 (28.10.2015, 12:04 UTC) +---------------------------------------- + +* LUN-2647 + + * history button made yellow + +No other commits. + +Revision 5352d52 (13.10.2015, 13:15 UTC) +---------------------------------------- + +* LUN-2643 + + * Prevent access to image/file changelist views. + * Remove useless stuff. + * Revert fix as view will not be accessible. + * . Remove the option to add files/images from their changelist/change admin view. + * Move styling fix so it will be used in both image and file changelists. + * Remove the "Add image" link from the admin/filer/image changelist view. + * Handle case when view is reached without an object. + +* Misc commits + + * Update server_backends.py. Replace deprecated method. + +Revision 49fdf9b (01.10.2015, 12:23 UTC) +---------------------------------------- + +No new issues. + +* Misc commits + + * Add migration 0002. + * Fixed related lookup popup icons + +Revision df8010a (24.09.2015, 11:12 UTC) +---------------------------------------- + +No new issues. + +* Misc commits + + * Django 1.8: fixed popup opening for add folder + * Django 1.8: updated extra context for custom admin view + * Django 1.8 upgrade: removed some django1.9 deprecation warnings + * Django 1.8 upgrade: updated test settings & fixed file/folder model related fields + +Revision 6cbcd3b (12.09.2015, 11:23 UTC) +---------------------------------------- + +* LUN-2620 + + * resize file/folder plugin popup + +No other commits. + +Revision eef2065 (04.09.2015, 09:05 UTC) +---------------------------------------- + +* LUN-2569 + + * 6.Revisit the layout of the filer upload pop-up window + +* LUN-2580 + + * fixes on sidebar + +* LUN-2596 + + * left align fieldsets + +* LUN-2603 + + * save button should appear when creating new folders on Filer + +No other commits. + +Revision 017a043 (28.08.2015, 08:51 UTC) +---------------------------------------- + +* LUN-2309 + + * collapsible fieldset style fix + * changed restricted link color changed + * add error messages wrapper only if they exist + * remove submit buttons padding around wrapper + * submit buttons updates + * updated manifest.in and .gitignore + * removed .sass-cache files + * filer updates for small resolutions and bug fixes + * updates after django upgrade + * remove deprecated function get_ordered_objects() + * Filer updates on forms + * Filer forms updates + * re-structure of change forms + * default boostrap updates + * Ace resources added to plugin + * updates on edit, delete pages + * Filer refactoring + +* Misc commits + + * Add .iml files to gitignore. + * Restore check for permission before rendering save buttons. + * copy-folder form updates + +Revision 0aca38c (03.08.2015, 09:19 UTC) +---------------------------------------- + +* LUN-1434 + + * -celery-task Added tests for trash management command. + * -celery-task Added celery task for take_out_filer_trash command. + +* LUN-2124 + + * Small optimization since this error in improbable. + * Added tests for restriction changes. + * Updated tests to expect warning messages instead of permission denied. + * Added warning messages for some possible incorrect usage cases. + +* LUN-2156 + + * Fixed widgets name clash. + * Refactor imports + * Adding new line + * Do not show Clear checkbox on Filer asset details form + +* Misc commits + + * added filer status command to check all files on storage + +Revision 9c535d2 (24.07.2015, 14:46 UTC) +---------------------------------------- + +No new issues. + +* Misc commits + + * Django 1.7 upgrade: Folder widget should be visible. + +Revision 3a18983 (17.07.2015, 13:47 UTC) +---------------------------------------- + +No new issues. + +* Misc commits + + * tox: Don't allow django 1.8 prereleases + * Django 1.7 upgrade: fixed dummy model for admin index page + * django 1.7 upgrade: fixed trash feature & deprecation warnings + * Django 1.7 upgrade; regenerated migrations + * Django 1.6 upgrade; fixed sites allowed on move action + * Django 1.6 upgrade changes + +Revision 9bdd109 (08.04.2015, 08:55 UTC) +---------------------------------------- + +No new issues. + +* Misc commits + + * django-mptt 0.7.1 was released recently, it doesn't work out of the box + +Revision 553cd36 (11.03.2015, 10:41 UTC) +---------------------------------------- + +No new issues. + +* Misc commits + + * Fix success message + +Revision b594c8f (03.03.2015, 12:20 UTC) +---------------------------------------- + +* LUN-1426 + + * fixed tests for folder destination filtering + * added destination cacndidates tree view for move action + +* LUN-1587 + + * displayed error mesages for zip extract process + * files with image extension but without valid image data will be ignored upon extraction. + +* Misc commits + + * deleted pytest leftovers + * added destination field to copy action template + +Revision db6f7e5 (06.02.2015, 12:23 UTC) +---------------------------------------- + +No new issues. + +* Misc commits + + * convert both str & unicode to unicode + +Revision d7f700c (05.11.2014, 16:58 UTC) +---------------------------------------- + +* LUN-1934 + + * fixed circular import reproducible when DEBUG is False * this happend while running management command from other apps that depend on filer. + +No other commits. + +Revision 77bf2d1 (21.10.2014, 11:16 UTC) +---------------------------------------- + +No new issues. + +* Misc commits + + * Switch the import order to avoid a circular dependcy in case filer.models is imported before filer.fields.image + +Revision 2606d5f (30.09.2014, 13:35 UTC) +---------------------------------------- + +No new issues. + +* Misc commits + + * Avoid upgrade to easy-thumbnails 2.x.x versions since would break the tests + +Revision a58cd5e (06.08.2014, 07:56 UTC) +---------------------------------------- + +* LUN-1762 + + * append popup params to files thumbnails + +No other commits. + +Revision ad5508f (13.06.2014, 12:26 UTC) +---------------------------------------- + +No new issues. + +* Misc commits + + * Set correct destination for test results in tox.ini + +Revision cdfe111 (17.04.2014, 12:31 UTC) +---------------------------------------- + +Changelog history starts here. diff --git a/Dockerfile.test b/Dockerfile.test new file mode 100644 index 000000000..0f2554268 --- /dev/null +++ b/Dockerfile.test @@ -0,0 +1,16 @@ +FROM python:3.12-slim + +WORKDIR /app + +# Install system deps needed for building Python packages +RUN apt-get update && apt-get install -y --no-install-recommends gcc && \ + rm -rf /var/lib/apt/lists/* + +# Copy the full source and install +COPY . . +RUN pip install --no-cache-dir pytest pytest-django filetype pytz "Django>=5.1,<5.2" && \ + pip install --no-cache-dir -e . + + +CMD ["pytest", "--ds=filer.test_settings", "filer/tests/"] + diff --git a/MANIFEST.in b/MANIFEST.in index 02878d577..699091990 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -6,3 +6,7 @@ include HISTORY recursive-include filer/templates * recursive-include filer/static * recursive-include filer/locale * +recursive-exclude filer/static/libs/bootstrap/.sass-cache * +exclude filer/static/libs/bootstrap/js/bootstrap.js +recursive-exclude filer/static/libs/bootstrap/sass * +exclude filer/static/libs/bootstrap/config.rb diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..7202313c9 --- /dev/null +++ b/Makefile @@ -0,0 +1,70 @@ +.PHONY: help +help: ## This help. + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n\nTargets:\n"} /^[a-zA-Z_-]+:.*?##/ { printf " \033[36m%-10s\033[0m %s\n", $$1, $$2 }' $(MAKEFILE_LIST) +.DEFAULT_GOAL := help + +.PHONY: bump-pbs bump-prekind build publish-nexus publish-nexus-dry-run + +IMAGE_NAME := django-filer-test +CONTAINER_NAME := django-filer-test-run +SHELL:=/bin/bash + +test-build: ## Build the test Docker image + docker build -f Dockerfile.test -t $(IMAGE_NAME) . + +test: ## Run unit tests in a Docker container + @if [ -z "$$(docker images -q $(IMAGE_NAME) 2>/dev/null)" ]; then \ + echo "Image not found, building..."; \ + $(MAKE) test-build; \ + fi + docker run --rm --name $(CONTAINER_NAME) $(IMAGE_NAME) + +test-verbose: test-build ## Run tests with verbose output and stop on first failure + docker run --rm --name $(CONTAINER_NAME) $(IMAGE_NAME) \ + pytest -vx --ds=filer.test_settings --pyargs filer.tests + +test-shell: test-build ## Open a shell in the test container (useful for debugging) + docker run --rm -it --name $(CONTAINER_NAME) $(IMAGE_NAME) /bin/bash + +test-clean: ## Remove the test Docker image + -docker rmi $(IMAGE_NAME) + + +bump-pbs: ## Bump PBS number: 3.4.4+pbs.3 -> 3.4.4+pbs.4 + bump-my-version bump --allow-dirty pbs + +bump-prekind: ## Bump prekind dev version: 3.4.4+pbs.3 -> 3.4.4+pbs.3.dev.g.YYYYMMDD. Pass sha= to override. + @current=$$(grep "^__version__" filer/__init__.py | sed "s/^__version__ = '//;s/'.*//"); \ + sha="$${sha:-$$(git rev-parse --short=8 HEAD)}"; \ + sha8="$${sha:0:8}"; \ + if echo "$$current" | grep -q '\.dev\.'; then \ + current_sha=$$(echo "$$current" | sed -nE "s/.*\.dev\.g([0-9a-f]{7,40})\.[0-9]{8}/\1/p"); \ + current_sha8="$${current_sha:0:8}"; \ + if [ "$$current_sha8" = "$$sha8" ]; then \ + echo "Nothing to bump: '$$current' already targets commit '$$sha8'. Create a new commit first or run 'make bump-pbs'."; \ + exit 1; \ + fi; \ + base=$$(echo "$$current" | sed -E "s/\.dev\.g[0-9a-f]+\.[0-9]{8}$$//"); \ + new_version="$$base.dev.g$$sha8.$$(date +%Y%m%d)"; \ + else \ + base="$$current"; \ + new_version="$$base.dev.g$$sha8.$$(date +%Y%m%d)"; \ + fi; \ + echo "Bumping: $$current -> $$new_version"; \ + sed -i.bak "s/__version__ = '$$current'/__version__ = '$$new_version'/" filer/__init__.py && rm -f filer/__init__.py.bak; \ + sed -i.bak -E "s/^current_version = \"[^\"]+\"/current_version = \"$$new_version\"/" .bumpversion.toml && rm -f .bumpversion.toml.bak + + +build: ## Build distribution packages (sdist and wheel) + rm -rf dist/ build/ *.egg-info + python3 -m pip install --upgrade --break-system-packages build + python3 -m build + +publish-nexus: build ## Publish to Nexus using ~/.pypirc config + python3 -m pip install --upgrade --break-system-packages twine + python3 -m twine upload -r nexus dist/* + +publish-nexus-dry-run: build ## Validate packages ready for Nexus (without uploading) + python3 -m pip install --upgrade --break-system-packages twine + python3 -m twine check dist/* + diff --git a/README.rst b/README.rst index 067599279..98ea4ec54 100644 --- a/README.rst +++ b/README.rst @@ -12,8 +12,8 @@ Wiki: https://github.com/stefanfoulis/django-filer/wiki Dependencies ------------ -* `Django`_ >= 1.3 (with ``django.contrib.staticfiles``) -* django-mptt >= 0.2.1 +* `Django`_ >=4.2 (with ``django.contrib.staticfiles``) +* `django-mptt`_ >= 0.2.1 * `easy_thumbnails`_ >= 1.0-alpha-17 * `django-polymorphic`_ >= 0.2 * `PIL`_ 1.1.7 (with JPEG and ZLIB support) diff --git a/README_PBS.md b/README_PBS.md new file mode 100644 index 000000000..40ba51006 --- /dev/null +++ b/README_PBS.md @@ -0,0 +1,150 @@ +# PBS Fork – Developer Guide + +## Versioning Scheme + +This fork uses a PBS-specific versioning scheme: + +``` ++pbs. +``` + +Example: `3.4.4+pbs.1`, `3.4.4+pbs.2` + +Development (pre-release) versions append a dev suffix: + +``` ++pbs..dev.g.YYYYMMDD +``` + +Example: `3.4.4+pbs.1.dev.g1a2b3c4d.20260617` + +The version is stored in `filer/__init__.py` and read dynamically by `pyproject.toml`. + +--- + +## Makefile Targets + +Run `make help` to see all available targets. Summary: + +| Target | Description | +|--------|-------------| +| `make help` | Show all available targets | +| `make test-build` | Build the test Docker image | +| `make test` | Run unit tests in a Docker container (builds image if missing) | +| `make test-verbose` | Run tests with verbose output, stop on first failure | +| `make test-shell` | Open a shell in the test container (for debugging) | +| `make test-clean` | Remove the test Docker image | +| `make bump-pbs` | Bump the PBS version number (e.g. `+pbs.1` → `+pbs.2`) | +| `make bump-prekind` | Create a dev pre-release version from the current commit | +| `make build` | Build sdist and wheel packages into `dist/` | +| `make publish-nexus` | Build and upload packages to Nexus | +| `make publish-nexus-dry-run` | Build and validate packages without uploading | + +--- + +## How to Publish a New Version + +### Prerequisites + +- Python 3 installed +- `bump-my-version` installed (`pip install bump-my-version`) +- `~/.pypirc` configured with a `[nexus]` section containing your repository URL and credentials + +### Steps + +#### 1. Run tests + +```bash +make test +``` + +Ensure all tests pass before proceeding. + +#### 2. Bump the PBS version + +```bash +make bump-pbs +``` + +This increments the PBS number (e.g. `3.4.4+pbs.1` → `3.4.4+pbs.2`) in both `filer/__init__.py` and `.bumpversion.toml`. + +#### 3. Commit and push + +```bash +git add filer/__init__.py .bumpversion.toml +git commit -m "Bump to $(grep __version__ filer/__init__.py | sed "s/.*'//;s/'.*//")" +git push +``` + +#### 4. Publish to Nexus + +```bash +make publish-nexus +``` + +This will: +1. Clean previous build artifacts +2. Build source distribution and wheel (`python3 -m build`) +3. Upload to Nexus using `twine` with the `[nexus]` section from `~/.pypirc` + +#### 5. (Optional) Validate without uploading + +```bash +make publish-nexus-dry-run +``` + +Runs `twine check` on the built packages to verify they are well-formed. + +--- + +## Publishing a Dev (Pre-release) Version + +Use this when you need to test unreleased changes without a formal PBS bump: + +```bash +make bump-prekind +``` + +This creates a version like `3.4.4+pbs.1.dev.g1a2b3c4d.20260617` based on the current HEAD commit and date. + +You can override the commit SHA: + +```bash +make bump-prekind sha=abc12345 +``` + +Then publish normally: + +```bash +make publish-nexus +``` + +> **Note:** To bump again on the same commit, you must first run `make bump-pbs` to move to the next PBS number. + +--- + +## Publishing via GitHub Actions (Bento3) + +You can also publish a new version using the **bento3** GitHub Actions workflow: + +🔗 [publish_django_filer.yml](https://github.com/pbs-digital/bento3/actions/workflows/publish_django_filer.yml) + +Trigger the workflow manually from the Actions tab. This is the recommended approach for CI-driven releases. + +--- + +## `~/.pypirc` Configuration (for local publishing) + +Ensure your `~/.pypirc` contains a `[nexus]` entry: + +```ini +[distutils] +index-servers = + nexus + +[nexus] +repository = https://your-nexus-instance/repository/pypi-hosted/ +username = your-username +password = your-password-or-token +``` + diff --git a/UPSTREAM_MERGE_FIXES.md b/UPSTREAM_MERGE_FIXES.md new file mode 100644 index 000000000..237a27d2e --- /dev/null +++ b/UPSTREAM_MERGE_FIXES.md @@ -0,0 +1,207 @@ +# Upstream Merge Fix Progress + +## Overview + +**Upstream source:** `https://github.com/django-cms/django-filer` (master branch, v3.4.4) +**Fork divergence:** Forked at tag `0.9` (commit `a9364960`), ~790 PBS vs ~1,977 upstream commits, 603 files changed. +**Target:** Django 5.1 / Python 3.12+ + +### Test Results Timeline + +| Stage | Failed | Passed | Skipped | +|-------|--------|--------|---------| +| Pre-merge (PBS baseline) | 0 | 153 | 68 | +| After upstream merge | 73 | ~80 | 68 | +| After Session 1 fixes | 67 | 86 | 68 | +| After Session 2 fixes | 59 | 94 | 68 | +| **After all fixes (final)** | **0** | **153** | **68** | + +--- + +## Fixes Applied + +### 1. `setup.py` — Build-time import error (GHA blocker) + +- **Problem:** `__import__('filer').__version__` fails because Django isn't installed in the build environment +- **Fix:** Replaced with regex-based `get_version()` that reads `filer/__init__.py` without importing +- **Also:** Removed deprecated `setuptools.command.test` references and `test_suite`/`tests_require` +- **Code:** + ```python + def get_version(): + """Read version from filer/__init__.py without importing the package.""" + init_py = os.path.join(os.path.dirname(__file__), 'filer', '__init__.py') + with open(init_py) as f: + match = re.search(r"^__version__\s*=\s*['\"]([^'\"]+)['\"]", f.read(), re.M) + if not match: + raise RuntimeError("Cannot find __version__ in filer/__init__.py") + return match.group(1) + ``` + +### 2. `filer/__init__.py` — PEP 440 version + +- **Problem:** `3.5.0.pbs.1` is invalid per PEP 440 +- **Fix:** Changed to `3.5.0+pbs.1` (local version identifier) + +### 3. `filer/models/abstract.py` — VILImage import + +- **Problem:** `from easy_thumbnails.VIL import Image` fails without `reportlab` +- **Fix:** Wrapped in try/except, set `VILImage = None` as fallback +- **Code:** + ```python + try: + from easy_thumbnails.VIL import Image as VILImage + except (ImportError, ModuleNotFoundError): + VILImage = None + ``` + +### 4. `filer/admin/fileadmin.py` — `display_canonical` FieldError + +- **Problem:** `get_readonly_fields` returned only model field names for restricted/core files, but fieldsets contain `display_canonical` (an admin method, not a model field) +- **Fix:** Appended `'display_canonical'` to the readonly fields list in that code path +- **Error:** `FieldError: Unknown field(s) (display_canonical) specified for File` + +### 5. `filer/templates/admin/filer/submit_line.html` — Delete URL with empty pk + +- **Problem:** `{% url opts|admin_urlname:'delete' obj.pk %}` failed when `obj.pk` was empty +- **Fix:** Changed to `original.pk` and added `and original.pk` guard + +### 6. `filer/admin/folderadmin.py` — Multiple fixes + +#### 6a. `destination_folders` AJAX view +- **Problem:** `NoReverseMatch: 'filer-destination_folders' not found` — the fancytree folder picker widget needed this URL +- **Fix:** Added AJAX view and URL pattern to `FolderAdmin.get_urls()` + +#### 6b. `move_file_to_clipboard` signature mismatch +- **Problem:** Both call sites passed wrong number of arguments +- **Fix:** Added missing `request` argument at both call sites + +#### 6c. `KeyError: 'name'` in folder form clean +- **Problem:** Folder form clean method assumed `'name'` was always in `cleaned_data` +- **Fix:** Added guard `if 'name' not in cleaned_data: return cleaned_data` + +#### 6d. `exclude` tuple incomplete +- **Problem:** Upstream had `exclude = ('parent',)` but PBS needs `('parent', 'owner', 'folder_type')` +- **Fix:** Restored full PBS exclude tuple + +#### 6e. `get_form()` — PBS field visibility logic +- **Problem:** Upstream `get_form()` didn't handle PBS-specific dynamic field visibility +- **Fix:** Restored full PBS logic: + - Hide `site`/`shared` for child folders and core folders + - Only show `shared` to superusers + - Pop `restricted` for add view + - Set `owner`/`parent` in clean method + +#### 6f. `_move_files_and_folders_impl` — MPTT corruption +- **Problem:** Upstream used bulk `update()` which bypasses MPTT tree updates and model signals +- **Fix:** Changed to individual `save()` calls to trigger MPTT tree recalculation + +#### 6g. `move_files_and_folders()` — PBS validation +- **Problem:** PBS site validation checks were missing from upstream's move implementation +- **Fix:** Restored: + - Root folder move prevention + - Site consistency checks (all moved items must belong to same site as destination) +- **Code:** + ```python + # PBS: prevent moving root folders + if folders_queryset.filter(parent=None).exists(): + messages.error(request, "To prevent potential problems, users " + "are not allowed to move root folders.") + return + # PBS: site consistency checks + sites_from_folders = \ + set(folders_queryset.values_list('site_id', flat=True)) | \ + set(files_queryset.exclude(folder__isnull=True).\ + values_list('folder__site_id', flat=True)) + if sites_from_folders and None in sites_from_folders: + messages.error(request, "Some of the selected files/folders " + "do not belong to any site.") + return + ``` + +#### 6h. `log_deletion` deprecation +- **Problem:** Dead `else` branches for Django < 5.1; bug where `files_queryset` was logged instead of `folders_queryset` +- **Fix:** Removed dead branches, fixed queryset reference + +### 7. `filer/server/backends/` — Server backend fixes (3 files) + +- **Files:** `default.py`, `nginx.py`, `xsendfile.py` +- **Problem 1:** `filer_file.mime_type` — `filer_file` is a `FieldFile` (not the `File` model), so it has no `mime_type` attribute +- **Fix 1:** Added `mimetypes.guess_type()` fallback +- **Problem 2:** `file_obj=filer_file.file` — `filer_file` is already the `FieldFile`, `.file` is the raw Python file object +- **Fix 2:** Changed to `file_obj=filer_file` +- **Error:** `AttributeError: 'MultiStorageFieldFile' has no attribute 'mime_type'` + +### 8. `filer/admin/views.py` — NewFolderForm missing `site` field + +- **Problem:** Form only had `fields = ('name',)`, ignoring PBS `site` field from POST data +- **Fix:** Added `'site'` to form fields: `fields = ('name', 'site')` + +### 9. `filer/templatetags/filermedia.py` — Deleted by upstream merge + +- **Problem:** Upstream deleted `filermedia.py` but 8+ templates still reference `{% load filermedia %}` +- **Fix:** Restored file with `filer_staticmedia_prefix` simple tag +- **Error:** `TemplateSyntaxError: 'filermedia' is not a registered tag library` + +### 10. `filer/admin/clipboardadmin.py` — Clipboard not created on upload + +- **Problem:** Upstream commented out `Clipboard.objects.get_or_create(user=request.user)` in `ajax_upload` +- **Fix:** Restored the get_or_create call so clipboard is created during upload +- **Error:** `Clipboard.DoesNotExist` + +### 11. `filer/tests/admin.py` — Test compatibility fixes + +- **Clipboard access:** Replaced `self.superuser.filer_clipboard` with `Clipboard.objects.get(user=self.superuser)` +- **Return values:** Removed `return folders, files` from test methods + +### 12. `filer/utils/cdn.py` — `modified_at` None guard + +- **Problem:** `get_cdn_url()` crashes with `TypeError: unsupported operand type(s) for +: 'NoneType' and 'datetime.timedelta'` when `file_obj.modified_at` is `None` +- **Fix:** Added early return `if file_obj.modified_at is None: return url` before the timedelta arithmetic +- **Error:** `TypeError: unsupported operand type(s) for +: 'NoneType' and 'datetime.timedelta'` + +--- + +## PBS-Specific Features Preserved + +These features exist in the PBS fork but not in upstream django-filer: + +| Feature | Description | +|---------|-------------| +| **Trash / Soft-delete** | Files/folders are soft-deleted to trash before permanent deletion | +| **Site-based permissions** | Folders belong to Django sites; users have site-scoped access | +| **Folder types** | `CORE_FOLDER`, `SITE_FOLDER` — restricts operations on system folders | +| **Restricted flag** | Files/folders can be marked restricted; cascades to children | +| **Shared folders** | M2M relationship allowing folders shared across sites | +| **CDN invalidation** | URL hashing and CDN cache invalidation on file changes | +| **S3/Botocore storage** | Multi-storage backend with S3 support | +| **Clipboard model** | Per-user clipboard for file operations | +| **Folder-affects-URL** | Hash-based filenames tied to folder structure | + +--- + +## Test Results — ✅ All Passing + +**Final result: 153 passed, 68 skipped, 0 failed** (matches PBS baseline) + +All 59 previously failing tests have been resolved. The upstream merge is fully compatible with the PBS test suite. + +--- + +## Files Modified (Summary) + +| File | Type of Change | +|------|---------------| +| `setup.py` | Build fix (regex version reader) | +| `filer/__init__.py` | PEP 440 version fix | +| `filer/models/abstract.py` | Import guard for VILImage | +| `filer/admin/fileadmin.py` | Readonly fields fix | +| `filer/admin/folderadmin.py` | 8 separate fixes (AJAX view, move/copy validation, MPTT, field visibility) | +| `filer/admin/views.py` | NewFolderForm site field | +| `filer/admin/clipboardadmin.py` | Clipboard creation restored | +| `filer/server/backends/default.py` | mime_type + file_obj fixes | +| `filer/server/backends/nginx.py` | mime_type + file_obj fixes | +| `filer/server/backends/xsendfile.py` | mime_type + file_obj fixes | +| `filer/templatetags/filermedia.py` | Restored deleted file | +| `filer/templates/admin/filer/submit_line.html` | Delete URL pk guard | +| `filer/tests/admin.py` | Test compatibility fixes | +| `filer/utils/cdn.py` | `modified_at` None guard for CDN URL | diff --git a/conftest.py b/conftest.py new file mode 100644 index 000000000..a91cddad2 --- /dev/null +++ b/conftest.py @@ -0,0 +1,9 @@ +import os + +collect_ignore = [ + os.path.join(os.path.dirname(__file__), "filer", "tests", "utils"), + os.path.join(os.path.dirname(__file__), "filer", "tests", "__init__.py"), + os.path.join(os.path.dirname(__file__), "filer", "contrib"), + os.path.join(os.path.dirname(__file__), "filer", "management"), +] + diff --git a/docs/settings.rst b/docs/settings.rst index 4dfd2ab30..c0f32e455 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -6,7 +6,7 @@ Settings ``FILER_ENABLE_PERMISSIONS`` ---------------------------- -Activate the or not the Permission check on the files and folders before +Activate the or not the Permission check on the files and folders before displaying them in the admin. When set to ``False`` it gives all the authorization to staff members based on standard Django model permissions. @@ -28,7 +28,7 @@ The prefix for static media where filer will look for bundled javascript, css and images. Defaults to ``/filer/`` if ``STATIC_URL`` is defined. Otherwise -falls back to ``/filer/``. It is the URL where the ``static/filer/`` +falls back to ``/filer/``. It is the URL where the ``static/filer/`` directory should be served. .. _FILER_STORAGES: @@ -122,15 +122,33 @@ Defaults to ``20`` ``FILER_SUBJECT_LOCATION_IMAGE_DEBUG`` -------------------------------------- -Draws a red circle around to point in the image that was used to do the +Draws a red circle around to point in the image that was used to do the subject location aware image cropping. Defaults to ``False`` -``FILER_ALLOW_REGULAR_USERS_TO_ADD_ROOT_FOLDERS`` -------------------------------------------------- +``FILER_FOLDER_AFFECTS_URL`` +---------------------------- + +Set this to ``True`` when your ``UPLOAD_TO`` function generates a path that depends on the +folder the file belongs to. -Regular users are not allowed to create new folders at the root level, only -subfolders of already existing folders, unless this setting is set to ``True``. +When renaming a file or moving it in and out of the clipboard the file is renamed/move on the +backend storage as well Defaults to ``False`` + + +``FILER_CDN_DOMAIN`` and ``FILER_CDN_INVALIDATION_TIME`` +-------------------------------------------------------- + +This settings and ``CDN_INVALIDATION_TIME`` are only useful if using a cdn and if when uploading a newer version of a file object the physical file gets overwritten on the storage backend. + +When the above condition is True: +* make sure you're storage backend returns urls that always point to the origin (NOT to the cdn) +* make ``FILER_CDN_DOMAIN`` point to the cdn distribution's domain +* set ``FILER_CDN_INVALIDATION_TIME`` to the time it takes the cdn to clear it's cache + +When a file object gets updated to a newer version, setting the above will result in: +* if the file's url is requested BEFORE the CDN got updated, the origin's domain will be used +* if the file's url is requested AFTER the CDN got updated, the cdn's domain will be used diff --git a/filer/__init__.py b/filer/__init__.py index c0325d34b..03cc0b520 100644 --- a/filer/__init__.py +++ b/filer/__init__.py @@ -1,3 +1,14 @@ -#-*- coding: utf-8 -*- -# version string following pep-0396 and pep-0386 -__version__ = '0.9' # pragma: nocover +""" +See PEP 386 (https://www.python.org/dev/peps/pep-0386/) + +Release logic: + 1. Increase version number (change __version__ below). + 2. Check that all changes have been documented in CHANGELOG.rst. + 3. git add filer/__init__.py CHANGELOG.rst + 4. git commit -m 'Bump to {new version}' + 5. git push + 6. Assure that all tests pass on CI + 7. Create a new release on github. +""" + +__version__ = '3.4.4+pbs.1' diff --git a/filer/admin/__init__.py b/filer/admin/__init__.py index 32b7da334..c84fb51b9 100644 --- a/filer/admin/__init__.py +++ b/filer/admin/__init__.py @@ -1,15 +1,43 @@ -#-*- coding: utf-8 -*- from django.contrib import admin -from filer.admin.clipboardadmin import ClipboardAdmin -from filer.admin.fileadmin import FileAdmin -from filer.admin.folderadmin import FolderAdmin -from filer.admin.imageadmin import ImageAdmin -from filer.admin.permissionadmin import PermissionAdmin -from filer.models import FolderPermission, Folder, File, Clipboard, Image +from ..models import Clipboard, File, Folder, FolderPermission +from ..settings import FILER_IMAGE_MODEL +from ..utils.loader import load_model +from .clipboardadmin import ClipboardAdmin +from .fileadmin import FileAdmin +from .folderadmin import FolderAdmin +from .imageadmin import ImageAdmin +from .permissionadmin import PermissionAdmin + +# PBS-specific: ThumbnailOption model may not exist in PBS migrations yet +try: + from ..models import ThumbnailOption + from .thumbnailoptionadmin import ThumbnailOptionAdmin + _has_thumbnail_option = True +except ImportError: + _has_thumbnail_option = False + +# PBS-specific: Trash admin +from ..admin.trashadmin import Trash, TrashAdmin + +Image = load_model(FILER_IMAGE_MODEL) admin.site.register(Folder, FolderAdmin) admin.site.register(File, FileAdmin) admin.site.register(Clipboard, ClipboardAdmin) admin.site.register(Image, ImageAdmin) admin.site.register(FolderPermission, PermissionAdmin) + +if _has_thumbnail_option: + admin.site.register(ThumbnailOption, ThumbnailOptionAdmin) + +# PBS-specific: register Trash admin +admin.site.register([Trash], TrashAdmin) + +# PBS-specific: Archive (backward compat) +try: + from ..models import Archive + from ..admin.archiveadmin import ArchiveAdmin + admin.site.register(Archive, ArchiveAdmin) +except ImportError: + pass diff --git a/filer/admin/archiveadmin.py b/filer/admin/archiveadmin.py new file mode 100644 index 000000000..2c30342b9 --- /dev/null +++ b/filer/admin/archiveadmin.py @@ -0,0 +1,13 @@ +from filer.admin.fileadmin import FileAdmin, FileAdminChangeFrom +from filer.models import Archive + + +class ArchiveAdminForm(FileAdminChangeFrom): + + class Meta: + model = Archive + exclude = () + + +class ArchiveAdmin(FileAdmin): + form = ArchiveAdminForm diff --git a/filer/admin/clipboardadmin.py b/filer/admin/clipboardadmin.py index cf403c7fd..fbcc41cf2 100644 --- a/filer/admin/clipboardadmin.py +++ b/filer/admin/clipboardadmin.py @@ -1,13 +1,29 @@ -#-*- coding: utf-8 -*- + +from django.contrib import admin, messages +from django.core.exceptions import ValidationError from django.forms.models import modelform_factory -from django.contrib import admin -from django.http import HttpResponse -from django.utils import simplejson +from django.http import JsonResponse +from django.urls import path, reverse +from django.utils.translation import gettext_lazy as _ from django.views.decorators.csrf import csrf_exempt -from filer import settings as filer_settings -from filer.models import Clipboard, ClipboardItem -from filer.utils.files import handle_upload, UploadException -from filer.utils.loader import load_object + +from .. import settings as filer_settings +from ..models import Clipboard, ClipboardItem, Folder +from ..settings import FILER_THUMBNAIL_ICON_SIZE +from ..utils.files import handle_request_files_upload, handle_upload, truncate_filename +from ..utils.loader import load_model +from ..validation import validate_upload +from . import views + + +NO_PERMISSIONS = _("You do not have permission to upload files.") +NO_FOLDER_ERROR = _("Can't find folder to upload. Please refresh and try again") +NO_PERMISSIONS_FOR_FOLDER = _( + "Can't use this folder, Permission Denied. Please select another folder." +) + + +Image = load_model(filer_settings.FILER_IMAGE_MODEL) # ModelAdmins @@ -18,85 +34,33 @@ class ClipboardItemInline(admin.TabularInline): class ClipboardAdmin(admin.ModelAdmin): model = Clipboard inlines = [ClipboardItemInline] - filter_horizontal = ('files',) raw_id_fields = ('user',) verbose_name = "DEBUG Clipboard" verbose_name_plural = "DEBUG Clipboards" + messages = { + 'already-exists': "File '{}' already exists in the clipboard.", + } def get_urls(self): - from django.conf.urls.defaults import patterns, url - urls = super(ClipboardAdmin, self).get_urls() - from filer import views - url_patterns = patterns('', - url(r'^operations/paste_clipboard_to_folder/$', - self.admin_site.admin_view(views.paste_clipboard_to_folder), - name='filer-paste_clipboard_to_folder'), - url(r'^operations/discard_clipboard/$', - self.admin_site.admin_view(views.discard_clipboard), - name='filer-discard_clipboard'), - url(r'^operations/delete_clipboard/$', - self.admin_site.admin_view(views.delete_clipboard), - name='filer-delete_clipboard'), - # upload does it's own permission stuff (because of the stupid - # flash missing cookie stuff) - url(r'^operations/upload/$', - self.ajax_upload, - name='filer-ajax_upload'), - ) - url_patterns.extend(urls) - return url_patterns - - @csrf_exempt - def ajax_upload(self, request, folder_id=None): - """ - receives an upload from the uploader. Receives only one file at the time. - """ - mimetype = "application/json" if request.is_ajax() else "text/html" - try: - upload, filename, is_raw = handle_upload(request) - - # Get clipboad - clipboard = Clipboard.objects.get_or_create(user=request.user)[0] - - # find the file type - for filer_class in filer_settings.FILER_FILE_MODELS: - FileSubClass = load_object(filer_class) - #TODO: What if there are more than one that qualify? - if FileSubClass.matches_file_type(filename, upload, request): - FileForm = modelform_factory( - model = FileSubClass, - fields = ('original_filename', 'owner', 'file') - ) - break - uploadform = FileForm({'original_filename': filename, - 'owner': request.user.pk}, - {'file': upload}) - if uploadform.is_valid(): - file_obj = uploadform.save(commit=False) - # Enforce the FILER_IS_PUBLIC_DEFAULT - file_obj.is_public = filer_settings.FILER_IS_PUBLIC_DEFAULT - file_obj.save() - clipboard_item = ClipboardItem( - clipboard=clipboard, file=file_obj) - clipboard_item.save() - json_response = { - 'thumbnail': file_obj.icons['32'], - 'alt_text': '', - 'label': unicode(file_obj), - } - return HttpResponse(simplejson.dumps(json_response), - mimetype=mimetype) - else: - form_errors = '; '.join(['%s: %s' % ( - field, - ', '.join(errors)) for field, errors in uploadform.errors.items() - ]) - raise UploadException("AJAX request not valid: form invalid '%s'" % (form_errors,)) - except UploadException, e: - return HttpResponse(simplejson.dumps({'error': unicode(e)}), - mimetype=mimetype) - - def get_model_perms(self, request): + return [ + path('operations/paste_clipboard_to_folder/', + self.admin_site.admin_view(views.paste_clipboard_to_folder), + name='filer-paste_clipboard_to_folder'), + path('operations/discard_clipboard/', + self.admin_site.admin_view(views.discard_clipboard), + name='filer-discard_clipboard'), + path('operations/delete_clipboard/', + self.admin_site.admin_view(views.delete_clipboard), + name='filer-delete_clipboard'), + path('operations/upload//', + ajax_upload, + name='filer-ajax_upload'), + path('operations/upload/no_folder/', + ajax_upload, + name='filer-ajax_upload'), + ] + super().get_urls() + + def get_model_perms(self, *args, **kwargs): """ It seems this is only used for the list view. NICE :-) """ @@ -105,3 +69,128 @@ def get_model_perms(self, request): 'change': False, 'delete': False, } + + +@csrf_exempt +def ajax_upload(request, folder_id=None): + """ + Receives an upload from the uploader. Receives only one file at a time. + """ + + if not request.user.has_perm("filer.add_file"): + messages.error(request, NO_PERMISSIONS) + return JsonResponse({'error': NO_PERMISSIONS}) + + if folder_id: + try: + # Get folder + folder = Folder.objects.get(pk=folder_id) + except Folder.DoesNotExist: + messages.error(request, NO_FOLDER_ERROR) + return JsonResponse({'error': NO_FOLDER_ERROR}) + else: + folder = Folder.objects.filter(pk=request.session.get('filer_last_folder_id', 0)).first() + + # check permissions + if folder and not folder.has_add_children_permission(request): + messages.error(request, NO_PERMISSIONS_FOR_FOLDER) + return JsonResponse({'error': NO_PERMISSIONS_FOR_FOLDER}) + + try: + if len(request.FILES) == 1: + # don't check if request is ajax or not, just grab the file + upload, filename, is_raw, mime_type = handle_request_files_upload(request) + else: + # else process the request as usual + upload, filename, is_raw, mime_type = handle_upload(request) + except Exception as e: + return JsonResponse({'error': str(e)}) + + # Truncate long filenames + filename = truncate_filename(upload, maxlen=100) + upload.name = filename + + # Re-detect mime_type after truncation may have added an extension + import mimetypes as _mimetypes + guessed_type = _mimetypes.guess_type(filename)[0] + if guessed_type and ( + mime_type == 'application/octet-stream' + or not _mimetypes.guess_all_extensions(mime_type) + ): + mime_type = guessed_type + + + # Get clipboard + clipboard = Clipboard.objects.get_or_create(user=request.user)[0] + + # Remove any stale clipboard entries with the same filename + # (e.g. from previous failed upload attempts) to allow re-upload + existing_in_clipboard = clipboard.files.filter(original_filename=filename) + if existing_in_clipboard.exists(): + # Get the actual file pks before clearing the M2M + stale_file_pks = list(existing_in_clipboard.values_list('pk', flat=True)) + ClipboardItem.objects.filter(clipboard=clipboard, file_id__in=stale_file_pks).delete() + from ..models import File as FilerFile + FilerFile.objects.filter(pk__in=stale_file_pks).delete() + + # find the file type + for filer_class in filer_settings.FILER_FILE_MODELS: + FileSubClass = load_model(filer_class) + # TODO: What if there are more than one that qualify? + if FileSubClass.matches_file_type(filename, upload, mime_type): + FileForm = modelform_factory( + model=FileSubClass, + fields=('original_filename', 'owner', 'file') + ) + break + uploadform = FileForm({'original_filename': filename, 'owner': request.user.pk}, + {'file': upload}) + uploadform.request = request + uploadform.instance.mime_type = mime_type + if uploadform.is_valid(): + try: + validate_upload(filename, upload, request.user, mime_type) + file_obj = uploadform.save(commit=False) + # Enforce the FILER_IS_PUBLIC_DEFAULT + file_obj.is_public = filer_settings.FILER_IS_PUBLIC_DEFAULT + except ValidationError as error: + messages.error(request, str(error)) + return JsonResponse({'error': str(error)}) + file_obj.folder = folder + try: + file_obj.save() + except Exception as error: + messages.error(request, str(error)) + return JsonResponse({'error': str(error)}) + clipboard_item = ClipboardItem( + clipboard=clipboard, file=file_obj) + clipboard_item.save() + + try: + thumbnail = None + data = { + 'thumbnail': thumbnail, + 'alt_text': '', + 'label': str(file_obj), + 'file_id': file_obj.pk, + } + # prepare preview thumbnail + if isinstance(file_obj, Image): + data['thumbnail_180'] = reverse( + f"admin:filer_{file_obj._meta.model_name}_fileicon", + args=(file_obj.pk, FILER_THUMBNAIL_ICON_SIZE), + ) + data['original_image'] = file_obj.url + return JsonResponse(data) + except Exception as error: + messages.error(request, str(error)) + return JsonResponse({"error": str(error)}) + else: + for key, error_list in uploadform.errors.items(): + for error in error_list: + messages.error(request, error) + + form_errors = '; '.join(['{}'.format( + ', '.join(errors)) for errors in list(uploadform.errors.values()) + ]) + return JsonResponse({'error': str(form_errors)}, status=200) diff --git a/filer/admin/common_admin.py b/filer/admin/common_admin.py new file mode 100644 index 000000000..c7771bc1a --- /dev/null +++ b/filer/admin/common_admin.py @@ -0,0 +1,244 @@ +#-*- coding: utf-8 -*- +from django.contrib import admin +from django.contrib.admin.utils import unquote +from django.contrib.admin.options import IS_POPUP_VAR +from django.contrib.auth import get_permission_codename +from django.urls import reverse, resolve +from django.http import HttpResponseRedirect + +from filer.models import Folder, File +from filer.utils.cms_roles import has_admin_role, has_role_on_site +from filer.admin.tools import has_multi_file_action_permission +from filer.views import (popup_param, selectfolder_param, popup_status, + selectfolder_status, current_site_param, + get_param_from_request) + + +class CommonModelAdmin(admin.ModelAdmin): + save_as = False + + def _make_restricted_field_readonly(self, user, obj=None): + perm = 'filer.can_restrict_operations' + can_restrict = user.has_perm(perm, obj) or user.has_perm(perm) + if not can_restrict or (obj and not obj.can_change_restricted(user)): + if 'restricted' not in self.readonly_fields: + self.readonly_fields += ['restricted'] + else: + if 'restricted' in self.readonly_fields: + self.readonly_fields.remove('restricted') + + def _get_post_url(self, obj): + """ + Needed to retrieve the changelist url as Folder/File can be extended + and admin url may change + """ + # Code borrowed from django ModelAdmin to determine + # changelist on the fly + opts = obj._meta + module_name = opts.model_name + return reverse('admin:%s_%s_changelist' % + (opts.app_label, module_name), + current_app=self.admin_site.name) + + def _get_parent_for_view(self, obj): + return obj.parent + + def _redirect_to_directory_listing( + self, request, response, expected_urls, parent, current_obj): + """ + Overrides the default to enable redirecting to the directory view after + change/delete of a file/folder. + """ + url = response.get("Location", None) + if url in expected_urls or url == self._get_post_url(current_obj): + return self._make_redirect_to_parent(request, parent) + return response + + def _make_redirect_to_parent(self, request, parent): + if parent: + url = reverse('admin:filer-directory_listing', kwargs={'folder_id': parent.id}) + else: + url = reverse('admin:filer-directory_listing-root') + + url = "%s%s%s%s" % (url, popup_param(request), + selectfolder_param(request, "&"), + current_site_param(request),) + return HttpResponseRedirect(url) + + + def delete_view(self, request, object_id, extra_context=None): + """ + Overrides the default to enable redirecting to the directory view after + deletion of a image. + + we need to fetch the object and find out who the parent is + before super, because super will delete the object and make it + impossible to find out the parent folder to redirect to. + """ + parent_folder = None + try: + obj = self.get_queryset(request).get(pk=unquote(object_id)) + parent_folder = self._get_parent_for_view(obj) + except self.model.DoesNotExist: + obj = None + expected_urls = ["../../../../", "../../"] + + response = super(CommonModelAdmin, self).delete_view( + request=request, object_id=object_id, + extra_context=extra_context) + + return self._redirect_to_directory_listing( + request, response, expected_urls, parent_folder, obj) + + def has_change_permission(self, request, obj=None): + """ + Implemented to allow auth backends to handle object permissions. + """ + opts = self.opts + if opts.auto_created: + # The model was auto-created as intermediary for a + # ManyToMany-relationship, find the target model + for field in opts.fields: + if field.remote_field and field.remote_field.model != self.parent_model: + opts = field.remote_field.model._meta + break + codename = get_permission_codename('change', opts) + perm_name, user = "{}.{}".format(opts.app_label, codename), request.user + return user.has_perm(perm_name, obj) or user.has_perm(perm_name) + + def has_delete_permission(self, request, obj=None): + """ + Implemented to allow auth backends to handle object permissions. + """ + if self.opts.auto_created: + # For link objects + return self.has_change_permission(request, obj) + codename = get_permission_codename('delete', self.opts) + perm_name, user = "{}.{}".format(self.opts.app_label, codename), request.user + return user.has_perm(perm_name, obj) or user.has_perm(perm_name) + + def render_change_form(self, request, context, add=False, change=False, + form_url='', obj=None): + context.update({ + 'current_site': get_param_from_request(request, 'current_site'), + 'show_delete': True, + 'is_popup': popup_status(request), + 'select_folder': selectfolder_status(request), + }) + return super(CommonModelAdmin, self).render_change_form( + request=request, context=context, add=add, + change=change, form_url=form_url, obj=obj) + + def response_change(self, request, obj): + """ + Overrides the default to be able to forward to the directory listing + instead of the default change_list_view + """ + parent_folder = self._get_parent_for_view(obj) + if IS_POPUP_VAR in request.POST: + # In popup we always want to see the parent after changes + return self._make_redirect_to_parent(request, parent_folder) + response = super(CommonModelAdmin, self).response_change(request, obj) + expected_urls = ['../', reverse('admin:index')] + return self._redirect_to_directory_listing( + request, response, expected_urls, parent_folder, obj) + + +class FolderPermissionModelAdmin(CommonModelAdmin): + + def has_add_permission(self, request): + # allow only make folder views + current_view = resolve(request.path_info).url_name + allowed_views = ( + 'filer-directory_listing-make_root_folder', + 'filer-directory_listing-make_folder', + ) + if current_view not in allowed_views: + return False + + folder_id = get_param_from_request(request, 'parent_id') + # Also check URL kwargs for folder_id + if not folder_id: + resolved = resolve(request.path_info) + folder_id = resolved.kwargs.get('folder_id') + if not folder_id: + # only site admins and superusers can add root folders + if has_admin_role(request.user): + return True + else: + folder = Folder.objects.get(id=folder_id) + return folder.has_add_permission(request.user) + return False + + def has_change_permission(self, request, obj=None): + folder = obj + can_change = super(FolderPermissionModelAdmin, self).\ + has_change_permission(request, folder) + + if not folder: + return request.user.has_perm('filer.can_use_directory_listing') + + return folder.has_change_permission(request.user) + + def has_view_permission(self, request, obj=None): + # In Django 4.2+, has_view_permission is checked separately from + # has_change_permission. Delegate to has_change_permission so that + # folders that deny change also deny the read-only view. + if obj: + return obj.has_change_permission(request.user) + return request.user.has_perm('filer.can_use_directory_listing') + + def has_delete_permission(self, request, obj=None): + folder = obj + can_delete = super(FolderPermissionModelAdmin, self).\ + has_delete_permission(request, obj) + + if not can_delete or not folder: + return can_delete + + if request.method == 'POST': + return has_multi_file_action_permission( + request, File.objects.none(), + Folder.objects.filter(id=folder.id)) + + return folder.has_delete_permission(request.user) + + def can_view_folder_content(self, request, folder): + if folder.is_readonly_for_user(request.user): + return True + # only admins can see site folders with no site owner + if not folder.site and has_admin_role(request.user): + return True + + if folder.site and has_role_on_site(request.user, folder.site): + return True + + return False + + +class FilePermissionModelAdmin(CommonModelAdmin): + + def _get_parent_for_view(self, obj): + return obj.folder + + def has_change_permission(self, request, obj=None): + can_change = super(FilePermissionModelAdmin, self).\ + has_change_permission(request, obj) + if not can_change or not obj: + return can_change + return obj.has_change_permission(request.user) + + def has_view_permission(self, request, obj=None): + # In Django 4.2+, delegate to has_change_permission so that + # files that deny change also deny the read-only view. + if obj: + return obj.has_change_permission(request.user) + return super(FilePermissionModelAdmin, self).has_view_permission( + request, obj) + + def has_delete_permission(self, request, obj=None): + can_delete = super(FilePermissionModelAdmin, self).\ + has_delete_permission(request, obj) + if not can_delete or not obj: + return can_delete + return obj.has_delete_permission(request.user) diff --git a/filer/admin/fileadmin.py b/filer/admin/fileadmin.py index f0756d1fe..7487e2846 100644 --- a/filer/admin/fileadmin.py +++ b/filer/admin/fileadmin.py @@ -1,48 +1,131 @@ -#-*- coding: utf-8 -*- +import mimetypes + from django import forms -from django.contrib.admin.util import unquote -from django.core.urlresolvers import reverse -from django.http import HttpResponseRedirect -from django.utils.translation import ugettext as _ -from filer import settings -from filer.admin.permissions import PrimitivePermissionAwareModelAdmin -from filer.models import File -from filer.views import (popup_param, selectfolder_param, popup_status, - selectfolder_status) +from django.contrib.admin.templatetags.admin_urls import admin_urlname +from django.contrib.admin.utils import unquote +from django.contrib.staticfiles.storage import staticfiles_storage +from django.db import models +from django.http import Http404, HttpResponse, HttpResponseRedirect +from django.shortcuts import get_object_or_404 +from django.urls import path, reverse +from django.utils.safestring import mark_safe +from django.utils.timezone import now +from django.utils.translation import gettext as _ + +from easy_thumbnails.engine import NoSourceGenerator +from easy_thumbnails.exceptions import InvalidImageFormatError +from easy_thumbnails.files import get_thumbnailer +from easy_thumbnails.models import Thumbnail as EasyThumbnail +from easy_thumbnails.options import ThumbnailOptions + +from .. import settings +from ..models import File +from ..settings import DEFERRED_THUMBNAIL_SIZES +from ..utils.loader import load_model +from .permissions import PrimitivePermissionAwareModelAdmin +from .tools import AdminContext, admin_url_params_encoded, popup_status + +# PBS-specific imports +from .common_admin import FilePermissionModelAdmin +from ..fields.file import NonClearableFileInput + +try: + from ..models import BaseImage +except ImportError: + BaseImage = None + +Image = load_model(settings.FILER_IMAGE_MODEL) class FileAdminChangeFrom(forms.ModelForm): class Meta: model = File + exclude = () + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + if "file" in self.fields: + self.fields["file"].widget = forms.FileInput() + # Pre-populate the "name" field with the original_filename when it is + # empty so that users see the current effective filename on first edit. + if self.instance and self.instance.pk and "name" in self.fields: + if not self.instance.name and self.instance.original_filename: + self.initial["name"] = self.instance.original_filename + + def clean(self): + from ..validation import validate_upload + cleaned_data = super().clean() + if "file" in self.changed_data and cleaned_data["file"]: + mime_type = mimetypes.guess_type(cleaned_data["file"].name)[0] or 'application/octet-stream' + file = cleaned_data["file"] + file.open("w+") # Allow for sanitizing upload + file.seek(0) + validate_upload( + file_name=cleaned_data["file"].name, + file=file.file, + owner=cleaned_data.get("owner"), + mime_type=mime_type, + ) + file.open("r") + return self.cleaned_data class FileAdmin(PrimitivePermissionAwareModelAdmin): list_display = ('label',) list_per_page = 10 search_fields = ['name', 'original_filename', 'sha1', 'description'] - raw_id_fields = ('owner',) - readonly_fields = ('sha1',) + readonly_fields = ('sha1', 'display_canonical') + form = FileAdminChangeFrom - # save_as hack, because without save_as it is impossible to hide the - # save_and_add_another if save_as is False. To show only save_and_continue - # and save in the submit row we need save_as=True and in - # render_change_form() override add and change to False. - save_as = True + formfield_overrides = { + models.FileField: {'widget': NonClearableFileInput}, + } - form = FileAdminChangeFrom + # PBS-specific: make fields readonly for restricted/core files + def get_readonly_fields(self, request, obj=None): + if obj and (obj.is_readonly_for_user(request.user) or + obj.is_restricted_for_user(request.user)): + return [field.name for field in obj.__class__._meta.fields] + ['display_canonical'] + readonly = list(self.readonly_fields) + self._make_restricted_field_readonly(request.user, obj) + if not request.user.is_superuser: + if 'owner' not in readonly: + readonly.append('owner') + return readonly + + def _make_restricted_field_readonly(self, user, obj): + """PBS: make restricted field readonly if user can't change restriction.""" + if obj and hasattr(obj, 'can_change_restricted'): + if not obj.can_change_restricted(user): + if 'restricted' not in self.readonly_fields: + self.readonly_fields = list(self.readonly_fields) + ['restricted'] @classmethod - def build_fieldsets(cls, extra_main_fields=(), extra_advanced_fields=(), extra_fieldsets=()): + def build_fieldsets(cls, extra_main_fields=(), extra_advanced_fields=(), + extra_fieldsets=()): fieldsets = ( (None, { - 'fields': ('name', 'owner', 'description',) + extra_main_fields, + 'fields': ( + 'title', + 'owner', + 'description', + ) + extra_main_fields, }), (_('Advanced'), { - 'fields': ('file', 'sha1',) + extra_advanced_fields, + 'fields': ( + 'file', + 'name', + 'sha1', + 'display_canonical', + ) + extra_advanced_fields, 'classes': ('collapse',), - }), - ) + extra_fieldsets + }), + (_('Permissions'), { + 'fields': ('restricted',), + 'classes': ('collapse', 'wide', 'extrapretty'), + }), + ) + extra_fieldsets if settings.FILER_ENABLE_PERMISSIONS: fieldsets = fieldsets + ( (None, { @@ -51,85 +134,130 @@ def build_fieldsets(cls, extra_main_fields=(), extra_advanced_fields=(), extra_f ) return fieldsets - def response_change(self, request, obj): - """ - Overrides the default to be able to forward to the directory listing - instead of the default change_list_view - """ - r = super(FileAdmin, self).response_change(request, obj) - if r['Location']: - # it was a successful save - if (r['Location'] in ['../'] or - r['Location'] == self._get_post_url(obj)): - # this means it was a save: redirect to the directory view - if obj.folder: - url = reverse('admin:filer-directory_listing', - kwargs={'folder_id': obj.folder.id}) - else: - url = reverse( - 'admin:filer-directory_listing-unfiled_images') - url = "%s%s%s" % (url,popup_param(request), - selectfolder_param(request,"&")) - return HttpResponseRedirect(url) + if ( + request.POST + and '_continue' not in request.POST + and '_saveasnew' not in request.POST + and '_addanother' not in request.POST + and '_edit_from_widget' not in request.POST + ): + if obj.folder: + url = reverse('admin:filer-directory_listing', + kwargs={'folder_id': obj.folder.id}) else: - # this means it probably was a save_and_continue_editing - pass - return r + url = reverse( + 'admin:filer-directory_listing-unfiled_images') + url = "{}{}".format( + url, + admin_url_params_encoded(request), + ) + return HttpResponseRedirect(url) + + template_response = super().response_change(request, obj) + if hasattr(template_response, 'context_data'): + template_response.context_data["media"] = self.media + return template_response def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None): - extra_context = {'show_delete': True, - 'is_popup': popup_status(request), - 'select_folder': selectfolder_status(request),} - context.update(extra_context) - return super(FileAdmin, self).render_change_form( - request=request, context=context, add=False, change=False, - form_url=form_url, obj=obj) + # PBS: flag readonly files to suppress submit buttons in template + is_readonly = obj and (obj.is_readonly_for_user(request.user) or + obj.is_restricted_for_user(request.user)) + context.update({ + 'show_delete': True, + 'history_url': admin_urlname(self.opts, 'history'), + 'expand_image_url': None, + 'is_popup': popup_status(request), + 'filer_admin_context': AdminContext(request), + 'is_readonly_file': is_readonly, + }) + if obj and obj.mime_maintype == 'image' and obj.file.exists(): + if 'svg' in obj.mime_type: + context['expand_image_url'] = reverse(admin_urlname(Image._meta, 'expand'), args=(obj.pk,)) + else: + context['expand_image_url'] = obj.file.url + return super().render_change_form( + request=request, context=context, add=add, change=change, + form_url=form_url, obj=obj) def delete_view(self, request, object_id, extra_context=None): - """ - Overrides the default to enable redirecting to the directory view after - deletion of a image. - - we need to fetch the object and find out who the parent is - before super, because super will delete the object and make it - impossible to find out the parent folder to redirect to. - """ - parent_folder = None try: - obj = self.queryset(request).get(pk=unquote(object_id)) + obj = self.get_queryset(request).get(pk=unquote(object_id)) parent_folder = obj.folder except self.model.DoesNotExist: - obj = None + parent_folder = None - r = super(FileAdmin, self).delete_view( - request=request, object_id=object_id, - extra_context=extra_context) - - url = r.get("Location", None) - # Check against filer_file_changelist as file deletion is always made by - # the base class - if (url in ["../../../../", "../../"] or - url == reverse("admin:filer_file_changelist")): + if request.POST: + super().delete_view( + request=request, object_id=object_id, + extra_context=extra_context) if parent_folder: url = reverse('admin:filer-directory_listing', - kwargs={'folder_id': parent_folder.id}) + kwargs={'folder_id': parent_folder.id}) else: url = reverse('admin:filer-directory_listing-unfiled_images') - url = "%s%s%s" % (url,popup_param(request), - selectfolder_param(request,"&")) + url = "{}{}".format( + url, + admin_url_params_encoded(request) + ) return HttpResponseRedirect(url) - return r + + return super().delete_view( + request=request, object_id=object_id, + extra_context=extra_context) + + def has_add_permission(self, request): + return False + + def has_change_permission(self, request, obj=None): + if not obj: + return False + return super().has_change_permission(request, obj) + + def has_view_permission(self, request, obj=None): + if not obj: + return False + return super().has_view_permission(request, obj) def get_model_perms(self, request): - """ - It seems this is only used for the list view. NICE :-) - """ return { 'add': False, 'change': False, 'delete': False, } -FileAdmin.fieldsets = FileAdmin.build_fieldsets() \ No newline at end of file + def display_canonical(self, instance): + canonical = instance.canonical_url + if canonical: + return mark_safe(f'{canonical}') + else: + return '-' + display_canonical.allow_tags = True + display_canonical.short_description = _('canonical URL') + + def get_urls(self): + return super().get_urls() + [ + path("icon//", + self.admin_site.admin_view(self.icon_view), + name=f"filer_{self.model._meta.model_name}_fileicon") + ] + + def icon_view(self, request, file_id: int, size: int) -> HttpResponse: + if size not in DEFERRED_THUMBNAIL_SIZES: + raise Http404 + file = get_object_or_404(File, pk=file_id) + if BaseImage and not isinstance(file, BaseImage): + raise Http404() + + try: + thumbnailer = get_thumbnailer(file) + thumbnail_options = ThumbnailOptions({'size': (size, size), "crop": True}) + thumbnail = thumbnailer.get_thumbnail(thumbnail_options, generate=True) + EasyThumbnail.objects.filter(name=thumbnail.name).update(modified=now()) + return HttpResponseRedirect(thumbnail.url) + except (InvalidImageFormatError, NoSourceGenerator): + return HttpResponseRedirect(staticfiles_storage.url('filer/icons/file-missing.svg')) + + +FileAdmin.fieldsets = FileAdmin.build_fieldsets() diff --git a/filer/admin/folderadmin.py b/filer/admin/folderadmin.py index e94745896..482d98b44 100644 --- a/filer/admin/folderadmin.py +++ b/filer/admin/folderadmin.py @@ -1,46 +1,60 @@ -#-*- coding: utf-8 -*- +import itertools +import logging +import os +import re +from collections import OrderedDict +from urllib.parse import quote as urlquote +from urllib.parse import unquote as urlunquote + +from django import VERSION as DJANGO_VERSION from django import forms -from django import template -from django.contrib import admin +from django.conf import settings as django_settings +from django.contrib import messages from django.contrib.admin import helpers -from django.contrib.admin.util import quote, unquote, capfirst -from django.template.defaultfilters import urlencode -from filer.admin.patched.admin_utils import get_deleted_objects -from django.core.exceptions import PermissionDenied -from django.core.paginator import Paginator, InvalidPage, EmptyPage -from django.core.urlresolvers import reverse -from django.db import router -from django.db.models import Q -from django.http import HttpResponseRedirect, Http404, HttpResponse -from django.shortcuts import render_to_response -from django.template import RequestContext -from django.utils.encoding import force_unicode -from django.utils.html import escape +from django.contrib.admin.utils import capfirst, quote, unquote +from django.core.exceptions import PermissionDenied, ValidationError +from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator +from django.db import models, router +from django.db.models import Case, F, OuterRef, Subquery, When +from django.db.models.functions import Coalesce, Lower +from django.http import HttpResponse, HttpResponseRedirect, JsonResponse +from django.shortcuts import get_object_or_404 +from django.template.response import TemplateResponse +from django.urls import path, reverse +from django.utils.encoding import force_str +from django.utils.html import escape, format_html from django.utils.safestring import mark_safe -from django.utils.translation import ugettext as _ -from django.utils.translation import ungettext, ugettext_lazy -from filer import settings -from filer.admin.forms import (CopyFilesAndFoldersForm, ResizeImagesForm, - RenameFilesForm) -from filer.admin.permissions import PrimitivePermissionAwareModelAdmin -from filer.views import (popup_status, popup_param, selectfolder_status, - selectfolder_param) -from filer.admin.tools import (userperms_for_request, - check_folder_edit_permissions, - check_files_edit_permissions, - check_files_read_permissions, - check_folder_read_permissions) -from filer.models import (Folder, FolderRoot, UnfiledImages, File, tools, - ImagesWithMissingData, FolderPermission, Image) -from filer.settings import FILER_STATICMEDIA_PREFIX, FILER_PAGINATE_BY -from filer.utils.filer_easy_thumbnails import FilerActionThumbnailer -from filer.thumbnail_processors import normalize_subject_location -from django.conf import settings as django_settings -import urllib -import os -import itertools -import inspect - +from django.utils.translation import gettext_lazy as _ +from django.utils.translation import ngettext_lazy + +from easy_thumbnails.models import Thumbnail + +from .. import settings +from ..cache import clear_folder_permission_cache +from ..models import File, Folder, FolderPermission, FolderRoot, ImagesWithMissingData, UnsortedImages, tools +from ..settings import ( + FILER_IMAGE_MODEL, FILER_PAGINATE_BY, FILER_TABLE_ICON_SIZE, FILER_THUMBNAIL_ICON_SIZE, TABLE_LIST_TYPE, +) +from ..thumbnail_processors import normalize_subject_location +from ..utils.compatibility import get_delete_permission +from ..utils.filer_easy_thumbnails import FilerActionThumbnailer +from ..utils.loader import load_model +from . import views +from .forms import CopyFilesAndFoldersForm, RenameFilesForm, ResizeImagesForm +from .patched.admin_utils import get_deleted_objects +from .permissions import PrimitivePermissionAwareModelAdmin +from .common_admin import FolderPermissionModelAdmin +from .tools import ( + AdminContext, admin_url_params_encoded, check_files_edit_permissions, check_files_read_permissions, + check_folder_edit_permissions, check_folder_read_permissions, get_directory_listing_type, + has_multi_file_action_permission, popup_status, + userperms_for_request, +) + + +Image = load_model(FILER_IMAGE_MODEL) + +logger = logging.getLogger(__name__) class AddFolderPopupForm(forms.ModelForm): folder = forms.HiddenInput() @@ -50,39 +64,143 @@ class Meta: fields = ('name',) -class FolderAdmin(PrimitivePermissionAwareModelAdmin): +class FolderAdmin(FolderPermissionModelAdmin): list_display = ('name',) - exclude = ('parent',) - list_per_page = 20 + exclude = ('parent', 'owner', 'folder_type') + list_per_page = 100 list_filter = ('owner',) - search_fields = ['name', 'files__name'] - raw_id_fields = ('owner',) + search_fields = ['name'] + autocomplete_fields = ['owner'] save_as = True # see ImageAdmin - actions = ['move_to_clipboard', 'files_set_public', 'files_set_private', - 'delete_files_or_folders', 'move_files_and_folders', - 'copy_files_and_folders', 'resize_images', 'rename_files'] + actions = ['delete_files_or_folders', 'move_files_and_folders', + 'copy_files_and_folders', 'resize_images', 'rename_files', + 'extract_files', + 'enable_restriction', 'disable_restriction'] + + if DJANGO_VERSION >= (5, 2): + directory_listing_template = 'admin/filer/folder/directory_listing.html' + else: # Remove this when Django 5.2 is the minimum version + directory_listing_template = 'admin/filer/folder/legacy_listing.html' + + order_by_file_fields = ['_file_size', 'original_filename', 'name', 'owner', + 'uploaded_at', 'modified_at'] + + def get_readonly_fields(self, request, obj=None): + self.readonly_fields = [ro_field + for ro_field in self.readonly_fields] + self._make_restricted_field_readonly(request.user, obj) + return super().get_readonly_fields(request, obj) + + def formfield_for_foreignkey(self, db_field, request=None, **kwargs): + from django.contrib.sites.models import Site + formfield = super().formfield_for_foreignkey( + db_field, request, **kwargs) + if request and db_field.remote_field.model is Site: + if request.user.is_superuser: + formfield.queryset = Site.objects.all() + else: + from filer.utils.cms_roles import get_admin_sites_for_user + admin_sites = [site.id + for site in get_admin_sites_for_user(request.user)] + formfield.queryset = Site.objects.filter(id__in=admin_sites) + return formfield + + def formfield_for_manytomany(self, db_field, request, **kwargs): + from django.contrib.sites.models import Site + formfield = super().formfield_for_manytomany( + db_field, request, **kwargs) + if request and db_field.remote_field.model is Site: + if request.user.is_superuser: + formfield.queryset = Site.objects.all() + else: + from filer.utils.cms_roles import get_admin_sites_for_user + admin_sites = [site.id + for site in get_admin_sites_for_user(request.user)] + formfield.queryset = Site.objects.filter(id__in=admin_sites) + return formfield def get_form(self, request, obj=None, **kwargs): """ Returns a Form class for use in the admin add view. This is used by add_view and change_view. + + Sets the parent folder and owner for the folder that will be edited + in the form. """ - parent_id = request.REQUEST.get('parent_id', None) - if parent_id: - return AddFolderPopupForm + parent_id = request.GET.get('parent_id', None) + if not parent_id: + parent_id = request.POST.get('parent_id', None) + + folder_form = super().get_form( + request, obj=obj, **kwargs) + + if 'site' in folder_form.base_fields: + folder_form.base_fields['site'].widget.can_add_related = False + folder_form.base_fields['site'].widget.can_delete_related = False + folder_form.base_fields['site'].widget.can_change_related = False + + if 'shared' in folder_form.base_fields: + folder_form.base_fields['shared'].widget.can_add_related = False + + # only show shared sites field for superusers + if not request.user.is_superuser: + folder_form.base_fields.pop('shared', None) + + # check if site field should be visible in the form + is_core_folder = False + if obj and obj.pk: + # change view + change_parent_id = obj.parent_id + is_core_folder = obj.is_core() else: - return super(FolderAdmin, self).get_form( - request, obj=None, **kwargs) + # add view + change_parent_id = parent_id + folder_form.base_fields.pop('restricted', None) + + # hide site/shared for child folders or core folders + pop_site_fields = change_parent_id or is_core_folder + if pop_site_fields: + folder_form.base_fields.pop('site', None) + folder_form.base_fields.pop('shared', None) + + def folder_form_clean(form_obj): + cleaned_data = form_obj.cleaned_data + if 'name' not in cleaned_data: + return cleaned_data + # make sure owner and parent are passed to the model clean method + current_folder = form_obj.instance + if not current_folder.owner: + current_folder.owner = request.user + if parent_id: + current_folder.parent = Folder.objects.get(id=parent_id) + folders_with_same_name = self.get_queryset(request).filter( + parent=form_obj.instance.parent, + name=cleaned_data['name']) + if form_obj.instance.pk: + folders_with_same_name = folders_with_same_name.exclude( + pk=form_obj.instance.pk) + if folders_with_same_name.exists(): + raise ValidationError( + 'Folder with this name already exists.') + return cleaned_data + + folder_form.clean = folder_form_clean + return folder_form def save_form(self, request, form, change): """ Given a ModelForm return an unsaved instance. ``change`` is True if the object is being changed, and False if it's being added. """ + if not change: + # New folder invalidates the folder permission cache (or it will not be visible) + clear_folder_permission_cache(request.user) r = form.save(commit=False) - parent_id = request.REQUEST.get('parent_id', None) + parent_id = request.GET.get('parent_id', None) + if not parent_id: + parent_id = request.POST.get('parent_id', None) if parent_id: - parent = Folder.objects.get(id=parent_id) + parent = self.get_queryset(request).get(id=parent_id) r.parent = parent return r @@ -91,34 +209,53 @@ def response_change(self, request, obj): Overrides the default to be able to forward to the directory listing instead of the default change_list_view """ - r = super(FolderAdmin, self).response_change(request, obj) - ## Code borrowed from django ModelAdmin to determine changelist on the fly - if r['Location']: - # it was a successful save - if (r['Location'] in ['../'] or - r['Location'] == self._get_post_url(obj)): - if obj.parent: - url = reverse('admin:filer-directory_listing', - kwargs={'folder_id': obj.parent.id}) - else: - url = reverse('admin:filer-directory_listing-root') - url = "%s%s%s" % (url,popup_param(request), - selectfolder_param(request,"&")) - return HttpResponseRedirect(url) + if ( + request.POST + and '_continue' not in request.POST + and '_saveasnew' not in request.POST + and '_addanother' not in request.POST + ): + + if obj.parent: + url = reverse('admin:filer-directory_listing', + kwargs={'folder_id': obj.parent.id}) else: - # this means it probably was a save_and_continue_editing - pass - return r + url = reverse('admin:filer-directory_listing-root') + url = "{}{}".format( + url, + admin_url_params_encoded(request), + ) + return HttpResponseRedirect(url) + return super().response_change(request, obj) def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None): + info = self.model._meta.app_label, self.model._meta.model_name extra_context = {'show_delete': True, + 'history_url': 'admin:%s_%s_history' % info, 'is_popup': popup_status(request), - 'select_folder': selectfolder_status(request),} + 'filer_admin_context': AdminContext(request)} context.update(extra_context) - return super(FolderAdmin, self).render_change_form( - request=request, context=context, add=False, - change=False, form_url=form_url, obj=obj) + return super().render_change_form( + request=request, context=context, add=add, + change=change, form_url=form_url, obj=obj) + + def add_view(self, request, *args, **kwargs): + raise PermissionDenied + + def make_folder(self, request, folder_id=None, *args, **kwargs): + response = super(FolderAdmin, self).add_view(request, *args, **kwargs) + + if (request.method == 'POST' and popup_status(request) and + not isinstance(response, HttpResponseRedirect)): + if hasattr(response, 'render'): + response = response.render() + content = getattr(response, 'content', b'') + if response.status_code == 200 and b'errorlist' not in content: + return HttpResponse('') + return response def delete_view(self, request, object_id, extra_context=None): """ @@ -128,79 +265,129 @@ def delete_view(self, request, object_id, extra_context=None): we need to fetch the object and find out who the parent is before super, because super will delete the object and make it impossible to find out the parent folder to redirect to. + + The delete_view breaks with polymorphic models if the cascade will + try delete objects that are of different polymorphic types + (AttributeError: 'File' object has no attribute 'file_ptr'). + The default implementation of the delete_view is hard to override + without just copying the whole big thing. Since we've already done + the overriding work on the delete_files_or_folders admin action, we + can re-use that here instead. """ - parent_folder = None try: - obj = self.queryset(request).get(pk=unquote(object_id)) + obj = self.get_queryset(request).get(pk=unquote(object_id)) parent_folder = obj.parent except self.model.DoesNotExist: - obj = None - - r = super(FolderAdmin, self).delete_view( - request=request, object_id=object_id, - extra_context=extra_context) - url = r.get("Location", None) - if url in ["../../../../", "../../"] or url == self._get_post_url(obj): + parent_folder = None + + # PBS: block deletion of core folders + if obj and not self.has_delete_permission(request, obj): + from django.http import HttpResponseForbidden + return HttpResponseForbidden("Permission denied") + + if request.POST: + self.delete_files_or_folders( + request, + files_queryset=File.objects.none(), + folders_queryset=self.get_queryset(request).filter(id=object_id) + ) if parent_folder: url = reverse('admin:filer-directory_listing', - kwargs={'folder_id': parent_folder.id}) + kwargs={'folder_id': parent_folder.id}) else: url = reverse('admin:filer-directory_listing-root') - url = "%s%s%s" % (url,popup_param(request), - selectfolder_param(request,"&")) + url = "{}{}".format( + url, + admin_url_params_encoded(request), + ) return HttpResponseRedirect(url) - return r + + return self.delete_files_or_folders( + request, + files_queryset=File.objects.none(), + folders_queryset=self.get_queryset(request).filter(id=object_id) + ) def icon_img(self, xs): - return mark_safe(('') % FILER_STATICMEDIA_PREFIX) + return format_html('Folder Icon', django_settings.STATIC_ROOT) icon_img.allow_tags = True def get_urls(self): - from django.conf.urls.defaults import patterns, url - urls = super(FolderAdmin, self).get_urls() - from filer import views - url_patterns = patterns('', + return [ # we override the default list view with our own directory listing # of the root directories - url(r'^$', self.admin_site.admin_view(self.directory_listing), - name='filer-directory_listing-root'), - url(r'^(?P\d+)/list/$', - self.admin_site.admin_view(self.directory_listing), - name='filer-directory_listing'), - - url(r'^(?P\d+)/make_folder/$', - self.admin_site.admin_view(views.make_folder), - name='filer-directory_listing-make_folder'), - url(r'^make_folder/$', - self.admin_site.admin_view(views.make_folder), - name='filer-directory_listing-make_root_folder'), - url(r'^images_with_missing_data/$', - self.admin_site.admin_view(self.directory_listing), - {'viewtype': 'images_with_missing_data'}, - name='filer-directory_listing-images_with_missing_data'), - url(r'^unfiled_images/$', - self.admin_site.admin_view(self.directory_listing), - {'viewtype': 'unfiled_images'}, - name='filer-directory_listing-unfiled_images'), - ) - url_patterns.extend(urls) - return url_patterns + path('', + self.admin_site.admin_view(self.directory_listing), + name='filer-directory_listing-root'), + + path('last/', + self.admin_site.admin_view(self.directory_listing), + {'viewtype': 'last'}, + name='filer-directory_listing-last'), + + path('/list/', + self.admin_site.admin_view(self.directory_listing), + name='filer-directory_listing'), + + path('/make_folder/', + self.admin_site.admin_view(self.make_folder), + name='filer-directory_listing-make_folder'), + path('make_folder/', + self.admin_site.admin_view(self.make_folder), + name='filer-directory_listing-make_root_folder'), + + path('images_with_missing_data/', + self.admin_site.admin_view(self.directory_listing), + {'viewtype': 'images_with_missing_data'}, + name='filer-directory_listing-images_with_missing_data'), + + path('unfiled_images/', + self.admin_site.admin_view(self.directory_listing), + {'viewtype': 'unfiled_images'}, + name='filer-directory_listing-unfiled_images'), + + path('destination_folders/', + self.admin_site.admin_view(self.destination_folders), + name='filer-destination_folders'), + ] + super().get_urls() # custom views def directory_listing(self, request, folder_id=None, viewtype=None): - clipboard = tools.get_user_clipboard(request.user) + if not request.user.has_perm("filer.can_use_directory_listing"): + raise PermissionDenied() + file_type = request.GET.get('file_type', None) if viewtype == 'images_with_missing_data': folder = ImagesWithMissingData() elif viewtype == 'unfiled_images': - folder = UnfiledImages() - elif folder_id == None: + # pass user in the class invocation, so that we can get + # access to the current user instance in the class + folder = UnsortedImages(user=request.user) + elif viewtype == 'last': + last_folder_id = request.session.get('filer_last_folder_id') + try: + self.get_queryset(request).get(id=last_folder_id) + except self.model.DoesNotExist: + url = reverse('admin:filer-directory_listing-root') + url = f"{url}{admin_url_params_encoded(request)}" + else: + url = reverse('admin:filer-directory_listing', kwargs={'folder_id': last_folder_id}) + url = f"{url}{admin_url_params_encoded(request)}" + return HttpResponseRedirect(url) + elif folder_id is None: folder = FolderRoot() else: - try: - folder = Folder.objects.get(id=folder_id) - except Folder.DoesNotExist: - raise Http404 + folder = get_object_or_404(self.get_queryset(request), id=folder_id) + request.session['filer_last_folder_id'] = folder_id + + list_type = get_directory_listing_type(request) or settings.FILER_FOLDER_ADMIN_DEFAULT_LIST_TYPE + if list_type == TABLE_LIST_TYPE: + # Prefetch thumbnails for table view + size = f"{FILER_TABLE_ICON_SIZE}x{FILER_TABLE_ICON_SIZE}" + size_x2 = f"{2 * FILER_TABLE_ICON_SIZE}x{2 * FILER_TABLE_ICON_SIZE}" + else: + # Prefetch thumbnails for thumbnail view + size = f"{FILER_THUMBNAIL_ICON_SIZE}x{FILER_THUMBNAIL_ICON_SIZE}" + size_x2 = f"{2 * FILER_THUMBNAIL_ICON_SIZE}x{2 * FILER_THUMBNAIL_ICON_SIZE}" # Check actions to see if any are available on this changelist actions = self.get_actions(request) @@ -214,42 +401,31 @@ def directory_listing(self, request, folder_id=None, viewtype=None): pass # search - def filter_folder(qs, terms=[]): - for term in terms: - qs = qs.filter(Q(name__icontains=term) | \ - Q(owner__username__icontains=term) | \ - Q(owner__first_name__icontains=term) | \ - Q(owner__last_name__icontains=term)) - return qs - - def filter_file(qs, terms=[]): - for term in terms: - qs = qs.filter(Q(name__icontains=term) | \ - Q(description__icontains=term) | \ - Q(original_filename__icontains=term) | \ - Q(owner__username__icontains=term) | \ - Q(owner__first_name__icontains=term) | \ - Q(owner__last_name__icontains=term)) - return qs - q = request.GET.get('q', None) + q = request.GET.get('q') if q: - search_terms = unquote(q).split(" ") + search_terms = urlunquote(q).split(' ') + search_mode = True else: search_terms = [] q = '' + search_mode = False + # Limit search results to current folder. limit_search_to_folder = request.GET.get('limit_search_to_folder', False) in (True, 'on') if len(search_terms) > 0: if folder and limit_search_to_folder and not folder.is_root: - folder_qs = folder.get_descendants() - file_qs = File.objects.filter( - folder__in=folder.get_descendants()) + desc_folder_ids = folder.get_descendants_ids() + # Do not include current folder itself in search results. + folder_qs = Folder.objects.filter(pk__in=desc_folder_ids) + # Limit search results to files in the current folder or any + # nested folder. + file_qs = File.objects.filter(folder_id__in=desc_folder_ids + [folder.pk]) else: - folder_qs = Folder.objects.all() + folder_qs = self.get_queryset(request) file_qs = File.objects.all() - folder_qs = filter_folder(folder_qs, search_terms) - file_qs = filter_file(file_qs, search_terms) + folder_qs = self.filter_folder(folder_qs, search_terms).prefetch_related("children", "all_files") + file_qs = self.filter_file(file_qs, search_terms) show_result_count = True else: @@ -257,66 +433,85 @@ def filter_file(qs, terms=[]): file_qs = folder.files.all() show_result_count = False - folder_qs = folder_qs.order_by('name') - file_qs = file_qs.order_by('name') - - folder_children = [] - folder_files = [] + # PBS: filter by file_type if requested + if file_type == 'image': + file_qs = file_qs.instance_of(Image) + + folder_qs = folder_qs.order_by('name').select_related("owner") + order_by = request.GET.get('order_by', None) + order_by_annotation = None + if order_by is None: + order_by_annotation = Lower(Coalesce( + Case( + When(name__exact='', then=None), + When(name__isnull=False, then='name') + ), + 'original_filename' + )) + + order_by = order_by.split(',') if order_by else [] + order_by = [field for field in order_by + if re.sub(r'^-', '', field) in self.order_by_file_fields] + if len(order_by) > 0: + file_qs = file_qs.order_by(*order_by) + elif order_by_annotation: + file_qs = file_qs.order_by(order_by_annotation) + + if folder.is_root and not search_mode: + virtual_items = folder.virtual_folders + else: + virtual_items = [] + + perms = FolderPermission.objects.get_read_id_list(request.user) + if perms != 'All': + file_qs = file_qs.filter( + models.Q(folder__id__in=perms) + | models.Q(folder_id__isnull=True) + | models.Q(owner=request.user) + ) + folder_qs = folder_qs.filter(models.Q(id__in=perms) | models.Q(owner=request.user)) + root_exclude_kwargs = {'parent__isnull': False, 'parent__id__in': perms} + else: + root_exclude_kwargs = {'parent__isnull': False} if folder.is_root: - folder_children += folder.virtual_folders - for f in folder_qs: - f.perms = userperms_for_request(f, request) - if hasattr(f, 'has_read_permission'): - if f.has_read_permission(request): - folder_children.append(f) - else: - pass - else: - folder_children.append(f) - for f in file_qs: - f.perms = userperms_for_request(f, request) - if hasattr(f, 'has_read_permission'): - if f.has_read_permission(request): - folder_files.append(f) - else: - pass - else: - folder_files.append(f) + folder_qs = folder_qs.exclude(**root_exclude_kwargs) + + # Annotate thumbnail status + thumbnail_qs = ( + Thumbnail.objects + .filter( + source__name=OuterRef("file"), + modified__gte=F("source__modified"), + ) + .exclude(name__contains="upscale") # TODO: Check WHY not used by directory listing + .order_by("-modified") + ) + file_qs = file_qs.annotate( + thumbnail_name=Subquery(thumbnail_qs.filter(name__contains=f"__{size}_").values_list("name")[:1]), + thumbnailx2_name=Subquery(thumbnail_qs.filter(name__contains=f"__{size_x2}_").values_list("name")[:1]) + ).select_related("owner") + try: permissions = { 'has_edit_permission': folder.has_edit_permission(request), 'has_read_permission': folder.has_read_permission(request), - 'has_add_children_permission': \ - folder.has_add_children_permission(request), + 'has_add_children_permission': + folder.has_add_children_permission(request), } - except: + except: # noqa permissions = {} - folder_files.sort() - items = folder_children + folder_files + + items = list(itertools.chain(folder_qs, file_qs)) paginator = Paginator(items, FILER_PAGINATE_BY) - # Make sure page request is an int. If not, deliver first page. - try: - page = int(request.GET.get('page', '1')) - except ValueError: - page = 1 - - # Are we moving to clipboard? - if request.method == 'POST' and '_save' not in request.POST: - for f in folder_files: - if "move-to-clipboard-%d" % (f.id,) in request.POST: - clipboard = tools.get_user_clipboard(request.user) - if f.has_edit_permission(request): - tools.move_file_to_clipboard([f], clipboard) - return HttpResponseRedirect(request.get_full_path()) - else: - raise PermissionDenied selected = request.POST.getlist(helpers.ACTION_CHECKBOX_NAME) - # Actions with no confirmation - if (actions and request.method == 'POST' and - 'index' in request.POST and '_save' not in request.POST): + if ( + actions and request.method == 'POST' + and 'index' in request.POST + and '_save' not in request.POST + ): if selected: response = self.response_action(request, files_queryset=file_qs, folders_queryset=folder_qs) if response: @@ -327,9 +522,12 @@ def filter_file(qs, terms=[]): self.message_user(request, msg) # Actions with confirmation - if (actions and request.method == 'POST' and - helpers.ACTION_CHECKBOX_NAME in request.POST and - 'index' not in request.POST and '_save' not in request.POST): + if ( + actions and request.method == 'POST' + and helpers.ACTION_CHECKBOX_NAME in request.POST + and 'index' not in request.POST + and '_save' not in request.POST + ): if selected: response = self.response_action(request, files_queryset=file_qs, folders_queryset=folder_qs) if response: @@ -342,44 +540,106 @@ def filter_file(qs, terms=[]): else: action_form = None - selection_note_all = ungettext('%(total_count)s selected', + selection_note_all = ngettext_lazy('%(total_count)s selected', 'All %(total_count)s selected', paginator.count) # If page request (9999) is out of range, deliver last page of results. try: - paginated_items = paginator.page(page) - except (EmptyPage, InvalidPage): + paginated_items = paginator.page(request.GET.get('page', 1)) + except PageNotAnInteger: + paginated_items = paginator.page(1) + except EmptyPage: paginated_items = paginator.page(paginator.num_pages) - return render_to_response( - 'admin/filer/folder/directory_listing.html', - { - 'folder': folder, - 'clipboard_files': File.objects.filter( - in_clipboards__clipboarditem__clipboard__user=request.user - ).distinct(), - 'paginator': paginator, - 'paginated_items': paginated_items, - 'permissions': permissions, - 'permstest': userperms_for_request(folder, request), - 'current_url': request.path, - 'title': u'Directory listing for %s' % folder.name, - 'search_string': ' '.join(search_terms), - 'q': urlencode(q), - 'show_result_count': show_result_count, - 'limit_search_to_folder': limit_search_to_folder, - 'is_popup': popup_status(request), - 'select_folder': selectfolder_status(request), - # needed in the admin/base.html template for logout links - 'root_path': reverse('admin:index'), - 'action_form': action_form, - 'actions_on_top': self.actions_on_top, - 'actions_on_bottom': self.actions_on_bottom, - 'actions_selection_counter': self.actions_selection_counter, - 'selection_note': _('0 of %(cnt)s selected') % {'cnt': len(paginated_items.object_list)}, - 'selection_note_all': selection_note_all % {'total_count': paginator.count}, - 'media': self.media, - 'enable_permissions': settings.FILER_ENABLE_PERMISSIONS - }, context_instance=RequestContext(request)) + + context = self.admin_site.each_context(request) + context.update({ + 'folder': folder, + 'paginator': paginator, + 'paginated_items': paginated_items, + 'virtual_items': virtual_items, + 'uploader_connections': settings.FILER_UPLOADER_CONNECTIONS, + 'max_files': settings.FILER_UPLOADER_MAX_FILES, + 'max_filesize': settings.FILER_UPLOADER_MAX_FILE_SIZE, + 'permissions': permissions, + 'permstest': userperms_for_request(folder, request), + 'current_url': request.path, + 'title': _('Directory listing for %(folder_name)s') % {'folder_name': folder.name}, + 'search_string': ' '.join(search_terms), + 'q': urlquote(q), + 'show_result_count': show_result_count, + 'folder_children': folder_qs, + 'folder_files': file_qs, + 'thumbnail_size': FILER_TABLE_ICON_SIZE if list_type == TABLE_LIST_TYPE else FILER_THUMBNAIL_ICON_SIZE, + 'limit_search_to_folder': limit_search_to_folder, + 'is_popup': popup_status(request), + 'filer_admin_context': AdminContext(request), + # needed in the admin/base.html template for logout links + 'root_path': reverse('admin:index'), + 'action_form': action_form, + 'actions_on_top': self.actions_on_top, + 'actions_on_bottom': self.actions_on_bottom, + 'actions_selection_counter': self.actions_selection_counter, + 'selection_note': _('0 of %(cnt)s selected') % {'cnt': len(paginated_items.object_list)}, + 'selection_note_all': selection_note_all % {'total_count': paginator.count}, + 'list_type': list_type, + 'list_type_template': settings.FILER_FOLDER_ADMIN_LIST_TYPE_SWITCHER_SETTINGS[list_type]['template'], + 'media': self.media, + 'enable_permissions': settings.FILER_ENABLE_PERMISSIONS, + 'can_make_folder': request.user.is_superuser or (folder.is_root and settings.FILER_ALLOW_REGULAR_USERS_TO_ADD_ROOT_FOLDERS) or permissions.get("has_add_children_permission"), + }) + return TemplateResponse(request, self.directory_listing_template, context) + + def filter_folder(self, qs, terms=()): + # Source: https://github.com/django/django/blob/1.7.1/django/contrib/admin/options.py#L939-L947 flake8: noqa + def construct_search(field_name): + if field_name.startswith('^'): + return "%s__istartswith" % field_name[1:] + elif field_name.startswith('='): + return "%s__iexact" % field_name[1:] + elif field_name.startswith('@'): + return "%s__search" % field_name[1:] + else: + return "%s__icontains" % field_name + + for term in terms: + filters = models.Q() + for filter_ in self.search_fields: + filters |= models.Q(**{construct_search(filter_): term}) + for filter_ in self.get_owner_filter_lookups(): + filters |= models.Q(**{filter_: term}) + qs = qs.filter(filters) + return qs + + def filter_file(self, qs, terms=()): + for term in terms: + filters = (models.Q(name__icontains=term) + | models.Q(description__icontains=term) + | models.Q(original_filename__icontains=term)) + for filter_ in self.get_owner_filter_lookups(): + filters |= models.Q(**{filter_: term}) + qs = qs.filter(filters) + return qs + + @property + def owner_search_fields(self): + """ + Returns all the fields that are CharFields except for password from the + User model. For the built-in User model, that means username, + first_name, last_name, and email. + """ + from django.contrib.auth import get_user_model + User = get_user_model() + + return [ + field.name for field in User._meta.fields + if isinstance(field, models.CharField) and field.name != 'password' + ] + + def get_owner_filter_lookups(self): + return [ + f'owner__{field}__icontains' + for field in self.owner_search_fields + ] def response_action(self, request, files_queryset, folders_queryset): """ @@ -424,7 +684,8 @@ def response_action(self, request, files_queryset, folders_queryset): # the action explicitly on all objects. selected = request.POST.getlist(helpers.ACTION_CHECKBOX_NAME) if not selected and not select_across: - # Reminder that something needs to be selected or nothing will happen + # Reminder that something needs to be selected or nothing + # will happen msg = _("Items must be selected in order to perform " "actions on them. No items have been changed.") self.message_user(request, msg) @@ -442,7 +703,8 @@ def response_action(self, request, files_queryset, folders_queryset): # Perform the action only on the selected objects files_queryset = files_queryset.filter(pk__in=selected_files) - folders_queryset = folders_queryset.filter(pk__in=selected_folders) + folders_queryset = folders_queryset.filter( + pk__in=selected_folders) response = func(self, request, files_queryset, folders_queryset) @@ -459,65 +721,40 @@ def response_action(self, request, files_queryset, folders_queryset): return None def get_actions(self, request): - actions = super(FolderAdmin, self).get_actions(request) + if settings.FILER_ENABLE_PERMISSIONS: + actions = OrderedDict() + actions['files_set_public'] = self.get_action('files_set_public') + actions['files_set_private'] = self.get_action('files_set_private') + actions.update(super().get_actions(request)) + else: + actions = super().get_actions(request) + if 'delete_selected' in actions: del actions['delete_selected'] return actions - def move_to_clipboard(self, request, files_queryset, folders_queryset): - """ - Action which moves the selected files and files in selected folders to clipboard. - """ - - if not self.has_change_permission(request): - raise PermissionDenied - - if request.method != 'POST': - return None - - clipboard = tools.get_user_clipboard(request.user) - - check_files_edit_permissions(request, files_queryset) - check_folder_edit_permissions(request, folders_queryset) - # TODO: Display a confirmation page if moving more than X files to clipboard? - - files_count = [0] # We define it like that so that we can modify it inside the move_files function - - def move_files(files): - files_count[0] += tools.move_file_to_clipboard(files, clipboard) - - def move_folders(folders): - for f in folders: - move_files(f.files) - move_folders(f.children.all()) - - move_files(files_queryset) - move_folders(folders_queryset) - - self.message_user(request, _("Successfully moved %(count)d files to clipboard.") % { - "count": files_count[0], - }) - - return None - - move_to_clipboard.short_description = ugettext_lazy("Move selected files to clipboard") - - def files_set_public_or_private(self, request, set_public, files_queryset, folders_queryset): + def files_set_public_or_private(self, request, set_public, files_queryset, + folders_queryset): """ - Action which enables or disables permissions for selected files and files in selected folders to clipboard (set them private or public). + Action which enables or disables permissions for selected files and + files in selected folders (set them private or public). """ if not self.has_change_permission(request): raise PermissionDenied - if request.method != 'POST': + permissions_enabled = settings.FILER_ENABLE_PERMISSIONS + + if request.method != 'POST' or not permissions_enabled: return None check_files_edit_permissions(request, files_queryset) check_folder_edit_permissions(request, folders_queryset) - files_count = [0] # We define it like that so that we can modify it inside the set_files function + # We define it like that so that we can modify it inside the + # set_files function + files_count = [0] def set_files(files): for f in files: @@ -535,35 +772,39 @@ def set_folders(folders): set_folders(folders_queryset) if set_public: - self.message_user(request, _("Successfully disabled permissions for %(count)d files.") % { - "count": files_count[0], - }) + self.message_user(request, _("Successfully disabled permissions for %(count)d files.") % {"count": files_count[0], }) else: - self.message_user(request, _("Successfully enabled permissions for %(count)d files.") % { - "count": files_count[0], - }) + self.message_user(request, _("Successfully enabled permissions for %(count)d files.") % {"count": files_count[0], }) return None def files_set_private(self, request, files_queryset, folders_queryset): - return self.files_set_public_or_private(request, False, files_queryset, folders_queryset) + return self.files_set_public_or_private(request, False, files_queryset, + folders_queryset) - files_set_private.short_description = ugettext_lazy("Enable permissions for selected files") + files_set_private.short_description = _("Enable permissions for selected files") def files_set_public(self, request, files_queryset, folders_queryset): - return self.files_set_public_or_private(request, True, files_queryset, folders_queryset) + return self.files_set_public_or_private(request, True, files_queryset, + folders_queryset) - files_set_public.short_description = ugettext_lazy("Disable permissions for selected files") + files_set_public.short_description = _("Disable permissions for selected files") + + def log_deletions(self, request, queryset): + """Log deletion for each object in the queryset.""" + for obj in queryset: + self.log_deletion(request, obj, str(obj)) def delete_files_or_folders(self, request, files_queryset, folders_queryset): """ Action which deletes the selected files and/or folders. This action first displays a confirmation page whichs shows all the - deleteable files and/or folders, or, if the user has no permission on one of the related - childs (foreignkeys), a "permission denied" message. + deletable files and/or folders, or, if the user has no permission on + one of the related childs (foreignkeys), a "permission denied" message. - Next, it delets all selected files and/or folders and redirects back to the folder. + Next, it deletes all selected files and/or folders and redirects back to + the folder. """ opts = self.model._meta app_label = opts.app_label @@ -572,58 +813,60 @@ def delete_files_or_folders(self, request, files_queryset, folders_queryset): if not self.has_delete_permission(request): raise PermissionDenied - current_folder = self._get_current_action_folder(request, files_queryset, folders_queryset) + # PBS: block deletion of readonly/core/restricted folders/files + if not has_multi_file_action_permission(request, files_queryset, folders_queryset): + messages.error(request, _("You do not have permission to delete " + "the selected files and/or folders.")) + return None + + current_folder = self._get_current_action_folder( + request, files_queryset, folders_queryset) all_protected = [] - # Populate deletable_objects, a data structure of all related objects that - # will also be deleted. - # Hopefully this also checks for necessary permissions. + # Populate deletable_objects, a data structure of all related objects + # that will also be deleted. Hopefully this also checks for necessary + # permissions. # TODO: Check if permissions are really verified - (args, varargs, keywords, defaults) = inspect.getargspec(get_deleted_objects) - if 'levels_to_root' in args: - # Django 1.2 - deletable_files, perms_needed_files = get_deleted_objects(files_queryset, files_queryset.model._meta, request.user, self.admin_site, levels_to_root=2) - deletable_folders, perms_needed_folders = get_deleted_objects(folders_queryset, folders_queryset.model._meta, request.user, self.admin_site, levels_to_root=2) - else: - # Django 1.3 - using = router.db_for_write(self.model) - deletable_files, perms_needed_files, protected_files = get_deleted_objects(files_queryset, files_queryset.model._meta, request.user, self.admin_site, using) - deletable_folders, perms_needed_folders, protected_folders = get_deleted_objects(folders_queryset, folders_queryset.model._meta, request.user, self.admin_site, using) - all_protected.extend(protected_files) - all_protected.extend(protected_folders) + using = router.db_for_write(self.model) + deletable_files, model_count_files, perms_needed_files, protected_files = get_deleted_objects(files_queryset, files_queryset.model._meta, request.user, self.admin_site, using) + deletable_folders, model_count_folder, perms_needed_folders, protected_folders = get_deleted_objects(folders_queryset, folders_queryset.model._meta, request.user, self.admin_site, using) + all_protected.extend(protected_files) + all_protected.extend(protected_folders) all_deletable_objects = [deletable_files, deletable_folders] all_perms_needed = perms_needed_files.union(perms_needed_folders) - # The user has already confirmed the deletion. - # Do the deletion and return a None to display the change list view again. + # The user has already confirmed the deletion. Do the deletion and + # return a None to display the change list view again. if request.POST.get('post'): if all_perms_needed: raise PermissionDenied n = files_queryset.count() + folders_queryset.count() if n: # delete all explicitly selected files + self.log_deletions(request, files_queryset) + # Still need to delete files individually (not only the database entries) for f in files_queryset: - self.log_deletion(request, f, force_unicode(f)) f.delete() # delete all files in all selected folders and their children - # This would happen automatically by ways of the delete cascade, but then the individual .delete() - # methods won't be called and the files won't be deleted from the filesystem. + # This would happen automatically by ways of the delete + # cascade, but then the individual .delete() methods won't be + # called and the files won't be deleted from the filesystem. folder_ids = set() for folder in folders_queryset: folder_ids.add(folder.id) - folder_ids.update(folder.get_descendants().values_list('id', flat=True)) - for f in File.objects.filter(folder__in=folder_ids): - self.log_deletion(request, f, force_unicode(f)) + folder_ids.update(folder.get_descendants_ids()) + qs = File.objects.filter(folder__in=folder_ids) + self.log_deletions(request, qs) + # Still need to delete files individually (not only the database entries) + for f in qs: f.delete() - # delete all folders - for f in folders_queryset: - self.log_deletion(request, f, force_unicode(f)) - f.delete() - self.message_user(request, _("Successfully deleted %(count)d files and/or folders.") % { - "count": n, - }) + # delete all folders individually to trigger soft-delete + self.log_deletions(request, folders_queryset) + for folder in folders_queryset: + folder.delete() + self.message_user(request, _("Successfully deleted %(count)d files and/or folders.") % {"count": n, }) # Return None to display the change list page again. return None @@ -632,7 +875,8 @@ def delete_files_or_folders(self, request, files_queryset, folders_queryset): else: title = _("Are you sure?") - context = { + context = self.admin_site.each_context(request) + context.update({ "title": title, "instance": current_folder, "breadcrumbs_action": _("Delete files and/or folders"), @@ -643,18 +887,20 @@ def delete_files_or_folders(self, request, files_queryset, folders_queryset): "protected": all_protected, "opts": opts, 'is_popup': popup_status(request), - 'select_folder': selectfolder_status(request), + 'filer_admin_context': AdminContext(request), "root_path": reverse('admin:index'), "app_label": app_label, "action_checkbox_name": helpers.ACTION_CHECKBOX_NAME, - } + }) # Display the destination folder selection page - return render_to_response([ - "admin/filer/delete_selected_files_confirmation.html" - ], context, context_instance=template.RequestContext(request)) + return TemplateResponse( + request, + "admin/filer/delete_selected_files_confirmation.html", + context + ) - delete_files_or_folders.short_description = ugettext_lazy("Delete selected files and/or folders") + delete_files_or_folders.short_description = _("Delete selected files and/or folders") # Copied from django.contrib.admin.util def _format_callback(self, obj, user, admin_site, perms_needed): @@ -666,20 +912,15 @@ def _format_callback(self, obj, user, admin_site, perms_needed): opts.app_label, opts.object_name.lower()), None, (quote(obj._get_pk_val()),)) - p = '%s.%s' % (opts.app_label, - opts.get_delete_permission()) + p = get_delete_permission(opts) if not user.has_perm(p): perms_needed.add(opts.verbose_name) # Display a link to the admin page. - return mark_safe(u'%s: %s' % - (escape(capfirst(opts.verbose_name)), - admin_url, - escape(obj))) + return format_html('{}: {}', escape(capfirst(opts.verbose_name)), admin_url, escape(obj)) else: # Don't display link to edit, because it either has no # admin or is edited inline. - return u'%s: %s' % (capfirst(opts.verbose_name), - force_unicode(obj)) + return f'{capfirst(opts.verbose_name)}: {force_str(obj)}' def _check_copy_perms(self, request, files_queryset, folders_queryset): try: @@ -699,7 +940,8 @@ def _check_move_perms(self, request, files_queryset, folders_queryset): return True return False - def _get_current_action_folder(self, request, files_queryset, folders_queryset): + def _get_current_action_folder(self, request, files_queryset, + folders_queryset): if files_queryset: return files_queryset[0].folder elif folders_queryset: @@ -731,43 +973,162 @@ def _list_all_destination_folders_recursive(self, request, folders_queryset, cur # We do not allow copying/moving back to the folder itself enabled = (allow_self or fo != current_folder) and fo.has_add_children_permission(request) - yield (fo, (mark_safe(("  " * level) + force_unicode(fo)), enabled)) - for c in self._list_all_destination_folders_recursive(request, folders_queryset, current_folder, fo.children.all(), allow_self, level + 1): - yield c + yield (fo, (mark_safe(("  " * level) + force_str(fo)), enabled)) + yield from self._list_all_destination_folders_recursive(request, folders_queryset, current_folder, fo.children.all(), allow_self, level + 1) def _list_all_destination_folders(self, request, folders_queryset, current_folder, allow_self): - return list(self._list_all_destination_folders_recursive(request, folders_queryset, current_folder, FolderRoot().children, allow_self, 0)) + root_folders = self.get_queryset(request).filter(parent__isnull=True).order_by('name') + return list(self._list_all_destination_folders_recursive(request, folders_queryset, current_folder, root_folders, allow_self, 0)) + + def destination_folders(self, request): + """ + AJAX view returning JSON list of destination folders for the fancytree + widget used in move/copy operations. + PBS: Filters by site access, excludes core folders and orphaned folders. + """ + import json + selected_folders_raw = request.GET.get('selected_folders', '[]') + try: + selected_ids = json.loads(selected_folders_raw) + except (json.JSONDecodeError, TypeError): + selected_ids = [] + selected_qs = self.get_queryset(request).filter(pk__in=selected_ids) + + current_folder_id = request.GET.get('current_folder') + current_folder = None + if current_folder_id and current_folder_id != 'null': + try: + current_folder = self.get_queryset(request).get(pk=int(current_folder_id)) + except (Folder.DoesNotExist, ValueError): + pass + + parent_raw = request.GET.get('parent') + if parent_raw and parent_raw != 'null': + try: + parent_id = int(parent_raw) + folders = self.get_queryset(request).filter(parent_id=parent_id).order_by('name') + except (ValueError, TypeError): + folders = self.get_queryset(request).filter(parent__isnull=True).order_by('name') + else: + folders = self.get_queryset(request).filter(parent__isnull=True).order_by('name') + + result = [] + for fo in folders: + if fo in selected_qs: + continue + if not fo.has_read_permission(request): + continue + # PBS: exclude core folders and orphaned folders (no site) as destinations + if fo.is_core(): + continue + if fo.parent is None and not fo.site: + continue + is_selectable = (fo != current_folder) and fo.has_add_children_permission(request) + has_children = fo.children.exists() + result.append({ + 'key': fo.pk, + 'title': fo.name, + 'folder': True, + 'lazy': has_children, + 'unselectable': not is_selectable, + }) + return JsonResponse(result, safe=False) def _move_files_and_folders_impl(self, files_queryset, folders_queryset, destination): for f in files_queryset: f.folder = destination f.save() - for f in folders_queryset: - f.move_to(destination, 'last-child') + for f_id in folders_queryset.values_list('id', flat=True): + f = Folder.objects.get(id=f_id) + f.parent = destination f.save() + def _validate_destination(self, request, destination, folders_queryset, current_folder, allow_self=False): + """ + Validate that destination is a legitimate target for copy/move without + recursively traversing the entire folder tree. Returns True if valid. + """ + if not destination.has_read_permission(request): + return False + if not destination.has_add_children_permission(request): + return False + if not allow_self and destination == current_folder: + return False + # Cannot move/copy into one of the selected folders or their descendants + selected_pks = set(folders_queryset.values_list('pk', flat=True)) + if destination.pk in selected_pks: + return False + # Check that destination is not a descendant of any selected folder + ancestor = destination.parent + while ancestor is not None: + if ancestor.pk in selected_pks: + return False + ancestor = ancestor.parent + return True + def move_files_and_folders(self, request, files_queryset, folders_queryset): opts = self.model._meta app_label = opts.app_label + # PBS: prevent moving root folders + if folders_queryset.filter(parent=None).exists(): + messages.error(request, "To prevent potential problems, users " + "are not allowed to move root folders. You may copy folders " + "and files.") + return + current_folder = self._get_current_action_folder(request, files_queryset, folders_queryset) perms_needed = self._check_move_perms(request, files_queryset, folders_queryset) to_move = self._list_all_to_copy_or_move(request, files_queryset, folders_queryset) - folders = self._list_all_destination_folders(request, folders_queryset, current_folder, False) if request.method == 'POST' and request.POST.get('post'): if perms_needed: raise PermissionDenied try: - destination = Folder.objects.get(pk=request.POST.get('destination')) - except Folder.DoesNotExist: + destination = self.get_queryset(request).get(pk=request.POST.get('destination')) + except self.model.DoesNotExist: raise PermissionDenied - folders_dict = dict(folders) - if destination not in folders_dict or not folders_dict[destination][1]: + if not self._validate_destination(request, destination, folders_queryset, current_folder): raise PermissionDenied + + # PBS: validate destination is not a core folder + if destination.is_core(): + messages.error(request, "You cannot move files/folders into a core folder.") + return None + + # PBS: site consistency checks + sites_from_folders = \ + set(folders_queryset.values_list('site_id', flat=True)) | \ + set(files_queryset.exclude(folder__isnull=True).\ + values_list('folder__site_id', flat=True)) + + if sites_from_folders and None in sites_from_folders: + messages.error(request, "Some of the selected files/folders " + "do not belong to any site. Folders need to be assigned " + "to a site before you can move files/folders from it.") + return + elif not destination.site: + messages.error(request, "The destination folder does not " + "belong to any site.") + return + elif len(sites_from_folders) > 1: + messages.error(request, "You cannot move files/folders that " + "belong to several sites. Select files/folders that " + "belong to only one site.") + return + elif (sites_from_folders and destination.site and + sites_from_folders.pop() != destination.site.id): + messages.error(request, "Selected files/folders need to " + "belong to the same site as the destination folder.") + return + # We count only topmost files and folders here n = files_queryset.count() + folders_queryset.count() - if n: + conflicting_names = [folder.name for folder in self.get_queryset(request).filter(parent=destination, name__in=folders_queryset.values('name'))] + if conflicting_names: + messages.error(request, _("Folders with names %s already exist at the selected " + "destination") % ", ".join(conflicting_names)) + elif n: self._move_files_and_folders_impl(files_queryset, folders_queryset, destination) self.message_user(request, _("Successfully moved %(count)d files and/or folders to folder '%(destination)s'.") % { "count": n, @@ -775,12 +1136,13 @@ def move_files_and_folders(self, request, files_queryset, folders_queryset): }) return None - context = { + context = self.admin_site.each_context(request) + context.update({ "title": _("Move files and/or folders"), "instance": current_folder, "breadcrumbs_action": _("Move files and/or folders"), "to_move": to_move, - "destination_folders": folders, + "destination_folders": [], "files_queryset": files_queryset, "folders_queryset": folders_queryset, "perms_lacking": perms_needed, @@ -788,14 +1150,12 @@ def move_files_and_folders(self, request, files_queryset, folders_queryset): "root_path": reverse('admin:index'), "app_label": app_label, "action_checkbox_name": helpers.ACTION_CHECKBOX_NAME, - } + }) # Display the destination folder selection page - return render_to_response([ - "admin/filer/folder/choose_move_destination.html" - ], context, context_instance=template.RequestContext(request)) + return TemplateResponse(request, "admin/filer/folder/choose_move_destination.html", context) - move_files_and_folders.short_description = ugettext_lazy("Move selected files and/or folders") + move_files_and_folders.short_description = _("Move selected files and/or folders") def _rename_file(self, file_obj, form_data, counter, global_counter): original_basename, original_extension = os.path.splitext(file_obj.original_filename) @@ -805,16 +1165,16 @@ def _rename_file(self, file_obj, form_data, counter, global_counter): current_basename = "" current_extension = "" file_obj.name = form_data['rename_format'] % { - 'original_filename': file_obj.original_filename, - 'original_basename': original_basename, - 'original_extension': original_extension, - 'current_filename': file_obj.name or "", - 'current_basename': current_basename, - 'current_extension': current_extension, - 'current_folder': file_obj.folder.name, - 'counter': counter + 1, # 1-based - 'global_counter': global_counter + 1, # 1-based - } + 'original_filename': file_obj.original_filename, + 'original_basename': original_basename, + 'original_extension': original_extension, + 'current_filename': file_obj.name or "", + 'current_basename': current_basename, + 'current_extension': current_extension, + 'current_folder': getattr(file_obj.folder, 'name', ''), + 'counter': counter + 1, # 1-based + 'global_counter': global_counter + 1, # 1-based + } file_obj.save() def _rename_files(self, files, form_data, global_counter): @@ -859,7 +1219,8 @@ def rename_files(self, request, files_queryset, folders_queryset): else: form = RenameFilesForm() - context = { + context = self.admin_site.each_context(request) + context.update({ "title": _("Rename files"), "instance": current_folder, "breadcrumbs_action": _("Rename files"), @@ -872,14 +1233,146 @@ def rename_files(self, request, files_queryset, folders_queryset): "root_path": reverse('admin:index'), "app_label": app_label, "action_checkbox_name": helpers.ACTION_CHECKBOX_NAME, - } + }) # Display the rename format selection page - return render_to_response([ - "admin/filer/folder/choose_rename_format.html" - ], context, context_instance=template.RequestContext(request)) + return TemplateResponse(request, "admin/filer/folder/choose_rename_format.html", context) - rename_files.short_description = ugettext_lazy("Rename files") + rename_files.short_description = _("Rename files") + + def extract_files(self, request, files_queryset, folders_queryset): + if request.method != 'POST': + return None + + from ..models import Archive + success_format = "Successfully extracted archive {}." + + # Filter by zip file extension rather than polymorphic_ctype, + # because zip files may have been uploaded as plain File instances + zip_extensions = Archive._filename_extensions # ['.zip'] + from django.db.models import Q + extension_filter = Q() + for ext in zip_extensions: + extension_filter |= Q(original_filename__iendswith=ext) + extension_filter |= Q(file__iendswith=ext) + files_queryset = files_queryset.filter(extension_filter) + + if not files_queryset.exists(): + self.message_user(request, _("No archive files were selected."), + level=messages.WARNING) + return None + + # cannot extract in unfiled files folder + if files_queryset.filter(folder__isnull=True).exists(): + raise PermissionDenied + + if not has_multi_file_action_permission(request, files_queryset, + Folder.objects.none()): + raise PermissionDenied + + def _as_archive(filer_file): + """Convert a File instance to Archive so extract methods work.""" + if isinstance(filer_file, Archive): + return filer_file + archive = Archive() + archive.__dict__.update(filer_file.__dict__) + archive.extract_errors = [] + return archive + + def is_valid_archive(filer_file): + is_valid = filer_file.is_valid() + if not is_valid: + error_format = "{} is not a valid zip file" + message = error_format.format(filer_file.clean_actual_name) + messages.error(request, _(message)) + return is_valid + + def has_collisions(filer_file): + collisions = filer_file.collisions() + if collisions: + error_format = "Files/Folders from {archive} with names:" + error_format += "{names} already exist." + names = ", ".join(collisions) + archive = filer_file.clean_actual_name + message = error_format.format( + archive=archive, + names=names, + ) + messages.error(request, _(message)) + return len(collisions) > 0 + + for f in files_queryset: + f = _as_archive(f) + if not is_valid_archive(f) or has_collisions(f): + continue + try: + f.extract() + message = success_format.format(f.actual_name) + self.message_user(request, _(message)) + for err_msg in f.extract_errors: + messages.warning( + request, + _("%s: %s" % (f.actual_name, err_msg)) + ) + except Exception as e: + logger.exception("Exception extracting file pk=%s: %s", f.pk, e) + messages.error(request, _("Error extracting %s: %s" % (f.actual_name, str(e)))) + return None + + extract_files.short_description = _("Extract selected zip files") + + def files_toggle_restriction(self, request, restriction, + files_qs, folders_qs): + """ + Action which enables or disables restriction for files/folders. + """ + if request.method != 'POST': + return None + # cannot restrict/unrestrict unfiled files + unfiled_files = files_qs.filter(folder__isnull=True) + if unfiled_files.exists(): + messages.warning(request, _("Some of the selected files do not have parents: %s, " + "so their rights cannot be changed.") % + ', '.join([str(unfiled_file) for unfiled_file in unfiled_files.all()])) + return None + + if not has_multi_file_action_permission(request, files_qs, folders_qs): + messages.warning(request, _("You are not allowed to modify the restrictions on " + "the selected files and folders.")) + return None + + count = [0] + + def set_files_or_folders(filer_obj): + for f in filer_obj: + if f.restricted != restriction: + f.restricted = restriction + f.save() + count[0] += 1 + + set_files_or_folders(files_qs) + set_files_or_folders(folders_qs) + count = count[0] + if restriction: + self.message_user(request, + _("Successfully enabled restriction for %(count)d files " + "and/or folders.") % {"count": count,}) + else: + self.message_user(request, + _("Successfully disabled restriction for %(count)d files " + "and/or folders.") % {"count": count,}) + + def enable_restriction(self, request, files_qs, folders_qs): + return self.files_toggle_restriction( + request, True, files_qs, folders_qs) + + enable_restriction.short_description = _("Enable role restriction for selected files and/or folders") + + def disable_restriction(self, request, files_qs, folders_qs): + return self.files_toggle_restriction( + request, False, files_qs, folders_qs) + + disable_restriction.short_description = _("Disable role restriction for selected files and/or folders") def _generate_new_filename(self, filename, suffix): basename, extension = os.path.splitext(filename) @@ -899,6 +1392,7 @@ def _copy_file(self, file_obj, destination, suffix, overwrite): file_obj.id = None file_obj.save() file_obj.folder = destination + file_obj._file_data_changed_hint = False # no need to update size, sha1, etc. file_obj.file = file_obj._copy_file(filename) file_obj.original_filename = self._generate_new_filename(file_obj.original_filename, suffix) file_obj.save() @@ -912,7 +1406,7 @@ def _get_available_name(self, destination, name): count = itertools.count(1) original = name while destination.contains_folder(name): - name = "%s_%s" % (original, count.next()) + name = f"{original}_{next(count)}" return name def _copy_folder(self, folder, destination, suffix, overwrite): @@ -927,11 +1421,11 @@ def _copy_folder(self, folder, destination, suffix, overwrite): old_folder = Folder.objects.get(pk=folder.pk) - # Due to how inheritance works, we have to set both pk and id to None - folder.pk = None - folder.id = None - folder.name = foldername - folder.insert_at(destination, 'last-child', True) # We save folder here + folder, _ = Folder.objects.get_or_create( + name=foldername, + owner=old_folder.owner, + parent=destination, + ) for perm in FolderPermission.objects.filter(folder=old_folder): perm.pk = None @@ -956,7 +1450,6 @@ def copy_files_and_folders(self, request, files_queryset, folders_queryset): current_folder = self._get_current_action_folder(request, files_queryset, folders_queryset) perms_needed = self._check_copy_perms(request, files_queryset, folders_queryset) to_copy = self._list_all_to_copy_or_move(request, files_queryset, folders_queryset) - folders = self._list_all_destination_folders(request, folders_queryset, current_folder, True) if request.method == 'POST' and request.POST.get('post'): if perms_needed: @@ -964,14 +1457,31 @@ def copy_files_and_folders(self, request, files_queryset, folders_queryset): form = CopyFilesAndFoldersForm(request.POST) if form.is_valid(): try: - destination = Folder.objects.get(pk=request.POST.get('destination')) - except Folder.DoesNotExist: + destination = self.get_queryset(request).get(pk=request.POST.get('destination')) + except self.model.DoesNotExist: raise PermissionDenied - folders_dict = dict(folders) - if destination not in folders_dict or not folders_dict[destination][1]: + if not self._validate_destination(request, destination, folders_queryset, current_folder): raise PermissionDenied + + # PBS: validate destination is not a core folder + if destination.is_core(): + messages.warning(request, _("The selected destination was not valid. " + "You cannot copy files/folders into a core folder.")) + return None + + # PBS: site consistency checks (same as move) + sites_from_folders = \ + set(folders_queryset.values_list('site_id', flat=True)) | \ + set(files_queryset.exclude(folder__isnull=True).\ + values_list('folder__site_id', flat=True)) + if sites_from_folders and destination.site and \ + any(s != destination.site_id for s in sites_from_folders if s is not None): + messages.warning(request, _("The selected destination was not valid. " + "Selected files/folders need to belong to the same site as the destination folder.")) + return None + if files_queryset.count() + folders_queryset.count(): - # We count all files and folders here (recursivelly) + # We count all files and folders here (recursively) n = self._copy_files_and_folders_impl(files_queryset, folders_queryset, destination, form.cleaned_data['suffix'], False) self.message_user(request, _("Successfully copied %(count)d files and/or folders to folder '%(destination)s'.") % { "count": n, @@ -984,15 +1494,19 @@ def copy_files_and_folders(self, request, files_queryset, folders_queryset): try: selected_destination_folder = int(request.POST.get('destination', 0)) except ValueError: - selected_destination_folder = 0 + if current_folder: + selected_destination_folder = current_folder.pk + else: + selected_destination_folder = 0 - context = { + context = self.admin_site.each_context(request) + context.update({ "title": _("Copy files and/or folders"), "instance": current_folder, "breadcrumbs_action": _("Copy files and/or folders"), "to_copy": to_copy, - "destination_folders": folders, - "selected_destination_folder": selected_destination_folder or current_folder.pk, + "destination_folders": [], + "selected_destination_folder": selected_destination_folder, "copy_form": form, "files_queryset": files_queryset, "folders_queryset": folders_queryset, @@ -1001,14 +1515,12 @@ def copy_files_and_folders(self, request, files_queryset, folders_queryset): "root_path": reverse('admin:index'), "app_label": app_label, "action_checkbox_name": helpers.ACTION_CHECKBOX_NAME, - } + }) # Display the destination folder selection page - return render_to_response([ - "admin/filer/folder/choose_copy_destination.html" - ], context, context_instance=template.RequestContext(request)) + return TemplateResponse(request, "admin/filer/folder/choose_copy_destination.html", context) - copy_files_and_folders.short_description = ugettext_lazy("Copy selected files and/or folders") + copy_files_and_folders.short_description = _("Copy selected files and/or folders") def _check_resize_perms(self, request, files_queryset, folders_queryset): try: @@ -1033,24 +1545,34 @@ def _list_all_to_resize(self, request, files_queryset, folders_queryset): return to_resize def _new_subject_location(self, original_width, original_height, new_width, new_height, x, y, crop): - # TODO: We could probably do better - return (round(new_width / 2), round(new_height / 2)) + # TODO: We could probably do even better, but this method knows nothing + # about actual thumbnailing algorithm details. + # It's better to reset subject location to the central point of the new + # image if the image is being cropped. The originally specified subject + # location could be outside of the new image. + if crop: + return int(new_width / 2), int(new_height / 2) + else: + # Calculate scaling factor of the new image compared to old. + scale = min(new_width / original_width, new_height / original_height) + return int(scale * x), int(scale * y) def _resize_image(self, image, form_data): original_width = float(image.width) original_height = float(image.height) - thumbnailer = FilerActionThumbnailer(file=image.file.file, name=image.file.name, source_storage=image.file.source_storage, thumbnail_storage=image.file.source_storage) + thumbnailer = FilerActionThumbnailer(file=image.file, name=image.file.name, source_storage=image.file.source_storage, thumbnail_storage=image.file.source_storage) # This should overwrite the original image new_image = thumbnailer.get_thumbnail({ - 'size': (form_data['width'], form_data['height']), + 'size': tuple(int(form_data[d] or 0) for d in ('width', 'height')), 'crop': form_data['crop'], 'upscale': form_data['upscale'], 'subject_location': image.subject_location, }) - from django.db.models.fields.files import ImageFieldFile image.file.file = new_image.file - image.generate_sha1() - image.save() # Also gets new width and height + # Since only file data was changed, there is no way for file field to know about the change. + # To update size, sha1, width and height fields let's call file_data_changed callback directly. + image.file_data_changed() + image.save() subject_location = normalize_subject_location(image.subject_location) if subject_location: @@ -1101,22 +1623,20 @@ def resize_images(self, request, files_queryset, folders_queryset): form.cleaned_data['crop'] = form.cleaned_data['thumbnail_option'].crop form.cleaned_data['upscale'] = form.cleaned_data['thumbnail_option'].upscale if files_queryset.count() + folders_queryset.count(): - # We count all files here (recursivelly) + # We count all files here (recursively) n = self._resize_images_impl(files_queryset, folders_queryset, form.cleaned_data) - self.message_user(request, _("Successfully resized %(count)d images.") % { - "count": n, - }) + self.message_user(request, _("Successfully resized %(count)d images.") % {"count": n, }) return None else: form = ResizeImagesForm() - context = { + context = self.admin_site.each_context(request) + context.update({ "title": _("Resize images"), "instance": current_folder, "breadcrumbs_action": _("Resize images"), "to_resize": to_resize, "resize_form": form, - "cmsplugin_enabled": 'cmsplugin_filer_image' in django_settings.INSTALLED_APPS, "files_queryset": files_queryset, "folders_queryset": folders_queryset, "perms_lacking": perms_needed, @@ -1124,11 +1644,9 @@ def resize_images(self, request, files_queryset, folders_queryset): "root_path": reverse('admin:index'), "app_label": app_label, "action_checkbox_name": helpers.ACTION_CHECKBOX_NAME, - } + }) # Display the resize options page - return render_to_response([ - "admin/filer/folder/choose_images_resize_options.html" - ], context, context_instance=template.RequestContext(request)) + return TemplateResponse(request, "admin/filer/folder/choose_images_resize_options.html", context) - resize_images.short_description = ugettext_lazy("Resize selected images") + resize_images.short_description = _("Resize selected images") diff --git a/filer/admin/forms.py b/filer/admin/forms.py index b49149ce5..a6c876719 100644 --- a/filer/admin/forms.py +++ b/filer/admin/forms.py @@ -1,40 +1,82 @@ from django import forms -from django.db import models from django.contrib.admin import widgets -from filer.utils.files import get_valid_filename -from django.utils.translation import ugettext as _ +from django.contrib.admin.helpers import AdminForm from django.core.exceptions import ValidationError -from django.conf import settings +from django.db import models +from django.utils.translation import gettext as _ + +from ..models import ThumbnailOption +from ..utils.files import get_valid_filename -if 'cmsplugin_filer_image' in settings.INSTALLED_APPS: - from cmsplugin_filer_image.models import ThumbnailOption +class WithFieldsetMixin: + def get_fieldsets(self): + return getattr(self, "fieldsets", [ + (None, {"fields": [field for field in self.fields]}) + ]) + + def admin_form(self): + "Returns a class contains the Admin fieldset to show form as admin form" + return AdminForm(self, self.get_fieldsets(), {}) class AsPWithHelpMixin(object): def as_p_with_help(self): - "Returns this form rendered as HTML

s with help text formated for admin." - return self._html_output( - normal_row=u'%(label)s %(field)s

%(help_text)s', - error_row=u'%s', - row_ender='

', - help_text_html=u'

%s

', - errors_on_separate_row=True) + "Returns this form rendered as HTML

s with help text formatted for admin." + from django.utils.html import conditional_escape + from django.utils.safestring import mark_safe + + output = [] + # Render non-field errors (e.g. from Form.clean()) + top_errors = self.non_field_errors() + if top_errors: + output.append(str(self.error_class(top_errors, renderer=self.renderer))) + + hidden_fields = [] + for name in self.fields: + bf = self[name] + # Collect hidden fields to render at the end + if bf.is_hidden: + if bf.errors: + for error in bf.errors: + output.append( + '

  • (Hidden field %s) %s
' + % (name, conditional_escape(error)) + ) + hidden_fields.append(str(bf)) + continue + + bf_errors = self.error_class(bf.errors) + if bf_errors: + output.append(str(bf_errors)) + css_classes = bf.css_classes() + html_class_attr = ' class="%s"' % css_classes if css_classes else '' + label = bf.label_tag() or '' + field = str(bf) + output.append('%s %s

' % (html_class_attr, label, field)) + if bf.help_text: + output.append('

%s

' % conditional_escape(bf.help_text)) + + # Append hidden fields at the end + if hidden_fields: + output.append(''.join(hidden_fields)) + + return mark_safe('\n'.join(output)) class CopyFilesAndFoldersForm(forms.Form, AsPWithHelpMixin): suffix = forms.CharField(required=False, help_text=_("Suffix which will be appended to filenames of copied files.")) # TODO: We have to find a way to overwrite files with different storage backends first. - #overwrite_files = forms.BooleanField(required=False, help_text=_("Overwrite a file if there already exists a file with the same filename?")) + # overwrite_files = forms.BooleanField(required=False, help_text=_("Overwrite a file if there already exists a file with the same filename?")) def clean_suffix(self): - valid = get_valid_filename(self.cleaned_data['suffix']) + valid = get_valid_filename(self.cleaned_data['suffix']) if self.cleaned_data['suffix'] else "" if valid != self.cleaned_data['suffix']: raise forms.ValidationError(_('Suffix should be a valid, simple and lowercase filename part, like "%(valid)s".') % {'valid': valid}) return self.cleaned_data['suffix'] -class RenameFilesForm(forms.Form, AsPWithHelpMixin): +class RenameFilesForm(WithFieldsetMixin, forms.Form): rename_format = forms.CharField(required=True) def clean_rename_format(self): @@ -50,16 +92,27 @@ def clean_rename_format(self): 'counter': 42, 'global_counter': 42, } - except KeyError, e: + except KeyError as e: raise forms.ValidationError(_('Unknown rename format value key "%(key)s".') % {'key': e.args[0]}) - except Exception, e: + except Exception as e: raise forms.ValidationError(_('Invalid rename format: %(error)s.') % {'error': e}) return self.cleaned_data['rename_format'] -class ResizeImagesForm(forms.Form, AsPWithHelpMixin): - if 'cmsplugin_filer_image' in settings.INSTALLED_APPS: - thumbnail_option = models.ForeignKey(ThumbnailOption, null=True, blank=True, verbose_name=_("thumbnail option")).formfield() +class ResizeImagesForm(WithFieldsetMixin, forms.Form): + fieldsets = ((None, {"fields": ( + "thumbnail_option", + ("width", "height"), + ("crop", "upscale"))}),) + + thumbnail_option = models.ForeignKey( + ThumbnailOption, + null=True, + blank=True, + verbose_name=_("thumbnail option"), + on_delete=models.CASCADE, + ).formfield() + width = models.PositiveIntegerField(_("width"), null=True, blank=True).formfield(widget=widgets.AdminIntegerFieldWidget) height = models.PositiveIntegerField(_("height"), null=True, blank=True).formfield(widget=widgets.AdminIntegerFieldWidget) crop = models.BooleanField(_("crop"), default=True).formfield() @@ -67,8 +120,5 @@ class ResizeImagesForm(forms.Form, AsPWithHelpMixin): def clean(self): if not (self.cleaned_data.get('thumbnail_option') or ((self.cleaned_data.get('width') or 0) + (self.cleaned_data.get('height') or 0))): - if 'cmsplugin_filer_image' in settings.INSTALLED_APPS: - raise ValidationError(_('Thumbnail option or resize parameters must be choosen.')) - else: - raise ValidationError(_('Resize parameters must be choosen.')) + raise ValidationError(_('Thumbnail option or resize parameters must be choosen.')) return self.cleaned_data diff --git a/filer/admin/imageadmin.py b/filer/admin/imageadmin.py index 2ed622273..aec3d41f9 100644 --- a/filer/admin/imageadmin.py +++ b/filer/admin/imageadmin.py @@ -1,49 +1,119 @@ -#-*- coding: utf-8 -*- from django import forms -from django.utils.translation import ugettext as _ -from filer import settings as filer_settings, settings -from filer.admin.fileadmin import FileAdmin -from filer.models import Image +from django.shortcuts import get_object_or_404 +from django.template.response import TemplateResponse +from django.urls import path +from django.utils.translation import gettext as _ +from django.utils.translation import gettext_lazy +from ..settings import FILER_IMAGE_MODEL +from ..thumbnail_processors import normalize_subject_location +from ..utils.compatibility import string_concat +from ..utils.loader import load_model +from .fileadmin import FileAdmin, FileAdminChangeFrom -class ImageAdminForm(forms.ModelForm): + +Image = load_model(FILER_IMAGE_MODEL) + + +class ImageAdminForm(FileAdminChangeFrom): subject_location = forms.CharField( - max_length=64, required=False, - label=_('Subject location'), - help_text=_('Location of the main subject of the scene.')) + max_length=64, required=False, + label=_('Subject location'), + help_text=_('Location of the main subject of the scene. ' + 'Format: "x,y".')) def sidebar_image_ratio(self): if self.instance: # this is very important. It forces the value to be returned as a - # string and always with a "." as seperator. If the conversion + # string and always with a "." as separator. If the conversion # from float to string is done in the template, the locale will # be used and in some cases there would be a "," instead of ".". # javascript would parse that to an integer. - return "%.6F" % self.instance.sidebar_image_ratio() + return '%.6F' % self.instance.sidebar_image_ratio() else: return '' + def _set_previous_subject_location(self, cleaned_data): + subject_location = self.instance.subject_location + cleaned_data['subject_location'] = subject_location + self.data = self.data.copy() + self.data['subject_location'] = subject_location + + def clean_subject_location(self): + """ + Validate subject_location preserving last saved value. + + Last valid value of the subject_location field is shown to the user + for subject location widget to receive valid coordinates on field + validation errors. + """ + subject_location = self.cleaned_data['subject_location'] + if not subject_location: + # if supplied subject location is empty, do not check it + return subject_location + + # use thumbnail's helper function to check the format + coordinates = normalize_subject_location(subject_location) + + if not coordinates: + err_msg = gettext_lazy('Invalid subject location format. ') + err_code = 'invalid_subject_format' + + elif ( + coordinates[0] > self.instance.width > 0 + or coordinates[1] > self.instance.height > 0 + ): + err_msg = gettext_lazy( + 'Subject location is outside of the image. ') + err_code = 'subject_out_of_bounds' + else: + return subject_location + + self._set_previous_subject_location(self.cleaned_data) + raise forms.ValidationError( + string_concat( + err_msg, + gettext_lazy('Your input: "{subject_location}". '.format( + subject_location=subject_location)), + 'Previous value is restored.'), + code=err_code) + class Meta: model = Image - - class Media: - css = { - #'all': (settings.MEDIA_URL + 'filer/css/focal_point.css',) - } - js = ( - filer_settings.FILER_STATICMEDIA_PREFIX + 'js/raphael.js', - filer_settings.FILER_STATICMEDIA_PREFIX + 'js/focal_point.js', - ) + exclude = () class ImageAdmin(FileAdmin): + change_form_template = 'admin/filer/image/change_form.html' form = ImageAdminForm + def get_urls(self): + return super().get_urls() + [ + path("expand/", + self.admin_site.admin_view(self.expand_view), + name=f"{self.opts.app_label}_{self.opts.model_name}_expand") + ] + + def expand_view(self, request, file_id): + image = get_object_or_404(self.model, pk=file_id) + return TemplateResponse( + request, + "admin/filer/image/expand.html", + context={ + "original_url": image.url + }, + ) + + +if FILER_IMAGE_MODEL == 'filer.Image': + extra_main_fields = ('author', 'default_alt_text', 'default_caption',) +else: + extra_main_fields = ('default_alt_text', 'default_caption',) ImageAdmin.fieldsets = ImageAdmin.build_fieldsets( - extra_main_fields=('default_alt_text', 'default_caption',), + extra_main_fields=extra_main_fields, extra_fieldsets=( - ('Subject Location', { + (_('Subject location'), { 'fields': ('subject_location',), 'classes': ('collapse',), }), diff --git a/filer/admin/patched/__init__.py b/filer/admin/patched/__init__.py index 53f7f2286..e69de29bb 100644 --- a/filer/admin/patched/__init__.py +++ b/filer/admin/patched/__init__.py @@ -1,2 +0,0 @@ -#-*- coding: utf-8 -*- - diff --git a/filer/admin/patched/admin_utils.py b/filer/admin/patched/admin_utils.py index cd9fb60ee..84602d5e5 100644 --- a/filer/admin/patched/admin_utils.py +++ b/filer/admin/patched/admin_utils.py @@ -1,30 +1,34 @@ -#-*- coding: utf-8 -*- """ Copy of ``django.contrib.admin.utils.get_deleted_objects`` and a subclass of -``django.contrib.admin.utils.NestedObjects`` that work with djongo_polymorphic querysets. -Ultimatly these should go directly into django_polymorphic or, in a more generic way, into django itself. +``django.contrib.admin.utils.NestedObjects`` that work with django-polymorphic +querysets. +Ultimately these should go directly into django-polymorphic or, in a more +generic way, into Django itself. -This code has been copied from -django 1.4. ``get_deleted_objects`` and ``NestedObjects`` have not changed compared to 1.3.1. +This code has been copied from Django 1.9.4. -At all locations where something has been changed, there are inline comments in the code. +At all locations where something has been changed, there are inline comments +in the code. """ -from django.contrib.admin.util import NestedObjects, quote -from django.utils.html import escape -from django.utils.safestring import mark_safe +from collections import defaultdict + +from django import VERSION as DJANGO_VERSION +from django.contrib.admin.utils import quote +from django.contrib.auth import get_permission_codename +from django.db import models +from django.db.models.deletion import Collector +from django.urls import NoReverseMatch, reverse +from django.utils.encoding import force_str +from django.utils.html import format_html from django.utils.text import capfirst -from django.utils.encoding import force_unicode -from django.core.urlresolvers import reverse def get_deleted_objects(objs, opts, user, admin_site, using): """ Find all objects related to ``objs`` that should also be deleted. ``objs`` - must be a homogenous iterable of objects (e.g. a QuerySet). - + must be a homogeneous iterable of objects (e.g. a QuerySet). Returns a nested list of strings suitable for display in the template with the ``unordered_list`` filter. - """ # --- begin patch --- collector = PolymorphicAwareNestedObjects(using=using) @@ -36,38 +40,115 @@ def format_callback(obj): has_admin = obj.__class__ in admin_site._registry opts = obj._meta + no_edit_link = '%s: %s' % (capfirst(opts.verbose_name), + force_str(obj)) + if has_admin: - admin_url = reverse('%s:%s_%s_change' - % (admin_site.name, - opts.app_label, - opts.object_name.lower()), - None, (quote(obj._get_pk_val()),)) + try: + admin_url = reverse('%s:%s_%s_change' + % (admin_site.name, + opts.app_label, + opts.model_name), + None, (quote(obj._get_pk_val()),)) + except NoReverseMatch: + # Change url doesn't exist -- don't display link to edit + return no_edit_link + p = '%s.%s' % (opts.app_label, - opts.get_delete_permission()) + get_permission_codename('delete', opts)) if not user.has_perm(p): perms_needed.add(opts.verbose_name) - # Display a link to the admin page. - return mark_safe(u'%s: %s' % - (escape(capfirst(opts.verbose_name)), - admin_url, - escape(obj))) + # Display a link to the admin page. + return format_html('{}: {}', + capfirst(opts.verbose_name), + admin_url, + obj) else: # Don't display link to edit, because it either has no # admin or is edited inline. - return u'%s: %s' % (capfirst(opts.verbose_name), - force_unicode(obj)) + return no_edit_link to_delete = collector.nested(format_callback) protected = [format_callback(obj) for obj in collector.protected] + model_count = {model._meta.verbose_name_plural: len(objs) for model, objs in collector.model_objs.items()} + + return to_delete, model_count, perms_needed, protected + + +class NestedObjects(Collector): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.edges = {} # {from_instance: [to_instances]} + self.protected = set() + self.model_objs = defaultdict(set) - return to_delete, perms_needed, protected + def add_edge(self, source, target): + self.edges.setdefault(source, []).append(target) + + def collect(self, objs, source=None, source_attr=None, **kwargs): + for obj in objs: + if source_attr and not source_attr.endswith('+'): + related_name = source_attr % { + 'class': source._meta.model_name, + 'app_label': source._meta.app_label, + } + self.add_edge(getattr(obj, related_name), obj) + else: + self.add_edge(None, obj) + self.model_objs[obj._meta.model].add(obj) + try: + return super().collect(objs, source_attr=source_attr, **kwargs) + except models.ProtectedError as e: + self.protected.update(e.protected_objects) + + if DJANGO_VERSION >= (3, 1): + def related_objects(self, related_model, related_fields, objs): + qs = super().related_objects(related_model, related_fields, objs) + return qs.select_related(*[related.name for related in related_fields]) + else: + def related_objects(self, related, objs): + qs = super().related_objects(related, objs) + return qs.select_related(related.field.name) + + def _nested(self, obj, seen, format_callback): + if obj in seen: + return [] + seen.add(obj) + children = [] + for child in self.edges.get(obj, ()): + children.extend(self._nested(child, seen, format_callback)) + if format_callback: + ret = [format_callback(obj)] + else: + ret = [obj] + if children: + ret.append(children) + return ret + + def nested(self, format_callback=None): + """ + Return the graph as a nested list. + """ + seen = set() + roots = [] + for root in self.edges.get(None, ()): + roots.extend(self._nested(root, seen, format_callback)) + return roots + + def can_fast_delete(self, *args, **kwargs): + """ + We always want to load the objects into memory so that we can display + them to the user in confirm page. + """ + return False class PolymorphicAwareNestedObjects(NestedObjects): - def collect(self, objs, source_attr=None, **kwargs): + def collect(self, objs, source_attr=None, **kwargs): if hasattr(objs, 'non_polymorphic'): - # .filter() is needed, because there may already be cached polymorphic results in the queryset + # .filter() is needed, because there may already be cached + # polymorphic results in the queryset objs = objs.non_polymorphic().filter() - return super(PolymorphicAwareNestedObjects, self).collect(objs, source_attr=source_attr, **kwargs) - + return super().collect( + objs, source_attr=source_attr, **kwargs) diff --git a/filer/admin/permissionadmin.py b/filer/admin/permissionadmin.py index ce4101a81..f3b03bd36 100644 --- a/filer/admin/permissionadmin.py +++ b/filer/admin/permissionadmin.py @@ -1,37 +1,56 @@ -#-*- coding: utf-8 -*- -import inspect +from django import VERSION as django_version from django.contrib import admin -from filer import settings -from filer.fields import folder +from django.contrib.auth import get_user_model +from django.utils.translation import gettext_lazy as _ + +from .. import settings +from ..cache import clear_folder_permission_cache class PermissionAdmin(admin.ModelAdmin): - fieldsets = ( - (None, {'fields': (('type', 'folder',))}), - (None, {'fields': (('user', 'group', 'everybody'),)}), - (None, {'fields': ( - ('can_edit', 'can_read', 'can_add_children') - )} - ), - ) - raw_id_fields = ('user', 'group',) - - def formfield_for_foreignkey(self, db_field, request, **kwargs): - db = kwargs.get('using') - if db_field.name == 'folder': - if 'admin_site' in inspect.getargspec(folder.AdminFolderWidget.__init__)[0]: # Django 1.4 - widget_instance = folder.AdminFolderWidget(db_field.rel, self.admin_site, using=db) - else: # Django <= 1.3 - widget_instance = folder.AdminFolderWidget(db_field.rel, using=db) - kwargs['widget'] = widget_instance - return super(PermissionAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs) + fieldsets = [ + (None, {'fields': ['type', 'folder']}), + (_("Who"), {'fields': ['user', 'group', 'everybody']}), + (_("What"), {'fields': ['can_edit', 'can_read', 'can_add_children']}), + ] + list_filter = ['group'] + list_display = ['pretty_logical_path', 'who', 'what'] + search_fields = ['user__username', 'group__name', 'folder__name'] + autocomplete_fields = ['user', 'group', 'folder'] + + class Media: + css = {'all': ['filer/css/admin_folderpermissions.css']} + + def get_autocomplete_fields(self, request): + """Remove "owner" from autocomplete_fields if User model has no search_fields""" + + autocomplete_fields = super().get_autocomplete_fields(request) + if django_version >= (5, 0): + user_admin = self.admin_site.get_model_admin(get_user_model()) + else: + user_admin = self.admin_site._registry[get_user_model()] + if not user_admin.get_search_fields(request): + autocomplete_fields.remove('user') + return autocomplete_fields + + def get_queryset(self, request): + qs = super().get_queryset(request) + return qs.prefetch_related("group", "folder") def get_model_perms(self, request): # don't display the permissions admin if permissions are disabled. # This method is easier for testing than not registering the admin at all at import time - enable_permissions = settings.FILER_ENABLE_PERMISSIONS + enable_permissions = settings.FILER_ENABLE_PERMISSIONS and request.user.has_perm('filer.add_folderpermission') return { 'add': enable_permissions, 'change': enable_permissions, 'delete': enable_permissions, } + + def save_model(self, request, obj, form, change): + clear_folder_permission_cache(request.user) + super().save_model(request, obj, form, change) + + def delete_model(self, request, obj): + clear_folder_permission_cache(request.user) + super().delete_model(request, obj) diff --git a/filer/admin/permissions.py b/filer/admin/permissions.py index beb24ee0e..a747990bc 100644 --- a/filer/admin/permissions.py +++ b/filer/admin/permissions.py @@ -1,9 +1,22 @@ -#-*- coding: utf-8 -*- +from django import VERSION as django_version from django.contrib import admin -from django.core.urlresolvers import reverse +from django.contrib.auth import get_user_model +from django.urls import reverse class PrimitivePermissionAwareModelAdmin(admin.ModelAdmin): + def get_autocomplete_fields(self, request): + """Remove "owner" from autocomplete_fields if User model has no search_fields""" + + autocomplete_fields = super().get_autocomplete_fields(request) + if django_version >= (5, 0): + user_admin = self.admin_site.get_model_admin(get_user_model()) + else: + user_admin = self.admin_site._registry[get_user_model()] + if not user_admin.get_search_fields(request) and 'owner' in autocomplete_fields: + autocomplete_fields.remove('owner') + return autocomplete_fields + def has_add_permission(self, request): # we don't have a "add" permission... but all adding is handled # by special methods that go around these permissions anyway @@ -24,11 +37,12 @@ def has_delete_permission(self, request, obj=None): return self.has_change_permission(request, obj) def _get_post_url(self, obj): - """ Needed to retrieve the changelist url as Folder/File can be extended - and admin url may change """ - ## Code borrowed from django ModelAdmin to determine changelist on the fly + """ + Needed to retrieve the changelist url as Folder/File can be extended + and admin url may change + """ + # Code from django ModelAdmin to determine changelist on the fly opts = obj._meta - module_name = opts.module_name return reverse('admin:%s_%s_changelist' % - (opts.app_label, module_name), + (opts.app_label, opts.model_name), current_app=self.admin_site.name) diff --git a/filer/admin/thumbnailoptionadmin.py b/filer/admin/thumbnailoptionadmin.py new file mode 100644 index 000000000..9bdf5ff26 --- /dev/null +++ b/filer/admin/thumbnailoptionadmin.py @@ -0,0 +1,5 @@ +from django.contrib import admin + + +class ThumbnailOptionAdmin(admin.ModelAdmin): + list_display = ('name', 'width', 'height') diff --git a/filer/admin/tools.py b/filer/admin/tools.py index f2268b9a3..66a75dd8c 100644 --- a/filer/admin/tools.py +++ b/filer/admin/tools.py @@ -1,5 +1,15 @@ -#-*- coding: utf-8 -*- +from django.conf import settings as django_settings +from django.contrib.admin.options import IS_POPUP_VAR from django.core.exceptions import PermissionDenied +from django.db.models import Q +from django.utils.http import urlencode + +from .. import settings +from ..utils.cms_roles import get_sites_for_user +from ..models.foldermodels import Folder + + +ALLOWED_PICK_TYPES = ('folder', 'file') def check_files_edit_permissions(request, files): @@ -40,3 +50,166 @@ def userperms_for_request(item, request): if x: r.append(p) return r + + +def popup_status(request): + return ( + IS_POPUP_VAR in request.GET + or 'pop' in request.GET + or IS_POPUP_VAR in request.POST + or 'pop' in request.POST + ) + + +def popup_pick_type(request): + pick_type = request.GET.get('_pick', request.POST.get('_pick')) + if pick_type in ALLOWED_PICK_TYPES: + return pick_type + return None + + +def edit_from_widget(request): + return request.GET.get('_edit_from_widget') == '1' + + +def get_directory_listing_type(request): + list_type = request.GET.get('_list_type', None) + if list_type not in settings.FILER_FOLDER_ADMIN_LIST_TYPE_CHOICES: + return + return list_type + + +def admin_url_params(request, params=None): + params = params or {} + if popup_status(request): + params[IS_POPUP_VAR] = '1' + pick_type = popup_pick_type(request) + if pick_type: + params['_pick'] = pick_type + if edit_from_widget(request): + params['_edit_from_widget'] = '1' + list_type = get_directory_listing_type(request) + if list_type and '_list_type' not in params.keys(): + params['_list_type'] = list_type + return params + + +def admin_url_params_encoded(request, first_separator='?', params=None): + params = urlencode( + sorted(admin_url_params(request, params=params).items()) + ) + if not params: + return '' + return f'{first_separator}{params}' + + +class AdminContext(dict): + def __init__(self, request): + super().__init__() + self.update(admin_url_params(request)) + + def __missing__(self, key): + if key == 'popup': + return self.get(IS_POPUP_VAR, False) == '1' + elif key == 'pick': + return self.get('_pick', '') + elif key.startswith('pick_'): + return self.get('_pick', '') == key.split('pick_')[1] + + def __getattr__(self, name): + if name in ('popup', 'pick') or name.startswith('pick_'): + return self.get(name) + raise AttributeError + + +# --- PBS-specific functions --- + +def is_valid_destination(request, folder): + user = request.user + if folder.is_readonly_for_user(user): + return False + if not folder.site: + return False + if user.is_superuser: + return True + if folder.is_restricted_for_user(request.user): + return False + if folder.site.id in get_sites_for_user(user): + return True + return False + + +def _filter_available_sites(current_site, user): + available_sites = get_sites_for_user(user) + if current_site: + current_site = float(current_site) + if not user.is_superuser and current_site not in available_sites: + available_sites = [] + else: + available_sites = [current_site] + return available_sites + + +def folders_available(current_site, user, folders_qs): + """ + Returns a queryset with folders that current user can see. + """ + available_sites = _filter_available_sites(current_site, user) + if not available_sites: + return folders_qs.none() + + core_folders = Q(folder_type=Folder.CORE_FOLDER) + shared_folders = Q(shared__in=available_sites) + accessible_site_folders = Q(site__in=available_sites) + + if user.is_superuser: + # superusers can also see folders with no site assigned + no_site_folders = Q(site__isnull=True) & ~core_folders + visible = (core_folders | shared_folders | + accessible_site_folders | no_site_folders) + else: + visible = core_folders | shared_folders | accessible_site_folders + + return folders_qs.filter(visible).distinct() + + +def has_multi_file_action_permission(request, files, folders): + """PBS: Check permissions for multi-file actions (move/copy/delete).""" + from ..utils.cms_roles import ( + has_admin_role, + get_admin_sites_for_user, + get_sites_for_user, + ) + # unfiled files can be moved/deleted so better to just exclude them + files = files.exclude(folder__isnull=True) + user = request.user + + if files.readonly(user).exists() or folders.readonly(user).exists(): + return False + if user.is_superuser: + return True + + if files.restricted(user).exists(): + return False + + if folders.restricted_descendants(user).exists(): + return False + + # only superusers can move/delete files/folders with no site ownership + if (files.filter(folder__site__isnull=True).exists() or + folders.filter(site__isnull=True).exists()): + return False + + _exists_root_folders = folders.filter(parent__isnull=True).exists() + if _exists_root_folders: + if not has_admin_role(user): + return False + sites_allowed = [s.id for s in get_admin_sites_for_user(user)] + else: + sites_allowed = get_sites_for_user(user) + + if (files.exclude(folder__site__in=sites_allowed).exists() or + folders.exclude(site__in=sites_allowed).exists()): + return False + + return True diff --git a/filer/admin/trashadmin.py b/filer/admin/trashadmin.py new file mode 100644 index 000000000..50ec1b3a9 --- /dev/null +++ b/filer/admin/trashadmin.py @@ -0,0 +1,233 @@ +from django.contrib import admin +from django.core.paginator import Paginator, InvalidPage, EmptyPage +from django.urls import reverse, re_path +from django.core.exceptions import PermissionDenied +from django.db.models import Q +from django.shortcuts import render, redirect +from django.http import HttpResponse, Http404 +from filer.utils.multi_model_qs import MultiMoldelQuerysetChain +from filer.settings import FILER_PAGINATE_BY +import filer +import json +import logging +import operator +from functools import reduce + +logger = logging.getLogger(__name__) + + +class Trash(object): + """Dummy model without any associated db table. + It's only purpose is to provide an additional + entry in the admin index. + """ + class _meta: + app_config = 'filer.apps.FilerConfig' + app_label = 'filer' # This is the app that the form will exist under + model_name = 'trash' # This is what will be used in the link url + object_name = 'Trash' + verbose_name_plural = 'Deleted Files and Folders' + verbose_name = 'Deleted Files and Folders' + permissions = () + swapped = False + abstract = False + + +class TrashAdmin(admin.ModelAdmin): + + class Meta: + model = Trash + + def get_urls(self): + urls = super(TrashAdmin, self).get_urls() + url_patterns = [ + re_path(r'^(?P\w+)/(?P\d+)/$', + self.admin_site.admin_view(self.restorable_item_view), + name='filer_trash_item'), + re_path(r'^(?P\w+)/(?P\d+)/restore/$', + self.admin_site.admin_view(self.restore_items), + name='filer_restore_items'), + re_path(r'^file/check/(?P\d+)/$', + self.admin_site.admin_view(self.file_check), + name='filer_trash_file_check'), + ] + url_patterns.extend(urls) + return url_patterns + + def get_queryset(self, request): + search_q = request.GET.get('q', '').split() + if search_q: + folders_q = reduce(operator.or_, + [Q(name__icontains=bit) for bit in search_q]) + files_q = reduce(operator.or_, + [Q(Q(name__icontains=bit) | + Q(original_filename__icontains=bit)) + for bit in search_q]) + else: + files_q = Q(folder__deleted_at__isnull=True) + folders_q = Q(Q(parent=None) | Q(parent__deleted_at__isnull=True)) + + file_qs = filer.models.filemodels.File.trash.filter(files_q) + folder_qs = filer.models.foldermodels.Folder.trash.filter(folders_q) + return MultiMoldelQuerysetChain([ + folder_qs.order_by('-deleted_at'), + file_qs.order_by('-deleted_at')]) + + def has_add_permission(self, request): + return False + + def has_change_permission(self, request, obj=None): + return request.user.is_superuser + + def has_delete_permission(self, request, obj=None): + return False + + def _get_restorable_parent(self, folder_id): + trashed = filer.models.Folder.all_objects.get( + id=folder_id).get_ancestors(include_self=True).filter( + deleted_at__isnull=False)[:1] + return trashed[0] if trashed else None + + def _check_restore_view_valid(self, request, filer_model, filer_obj_id): + if not self.has_change_permission(request, None): + raise PermissionDenied + + if filer_model not in ['file', 'folder']: + logger.warning( + 'Restorable view for model %s is not available' % filer_model) + raise Http404 + + filer_model_cls = getattr(filer.models, filer_model.capitalize()) + try: + filer_object = filer_model_cls.trash.get(id=filer_obj_id) + except filer_model_cls.DoesNotExist as e: + raise Http404 + + return filer_model_cls, filer_object + + def restorable_item_view(self, request, filer_model, filer_obj_id): + opts = self.model._meta + filer_model_cls, filer_object = self._check_restore_view_valid( + request, filer_model, filer_obj_id) + # if this item cannot be restored alone, redirect to the nearest + # ancestor that is allowed to be restored + if filer_model == 'folder': + # a folder can be restored only if its parent is not in trash + restorable_item = self._get_restorable_parent(filer_object.id) + if restorable_item and restorable_item.id != filer_object.id: + return redirect(reverse( + 'admin:filer_trash_item', + args=['folder', restorable_item.id])) + + descendants = filer_object.get_descendants(include_self=True).\ + select_related('parent').filter(deleted_at__isnull=False) + else: + # a single file can be restored only if it's folder is not in trash + if filer_object.folder_id: + restorable_item = self._get_restorable_parent( + filer_object.folder_id) + if restorable_item: + return redirect(reverse( + 'admin:filer_trash_item', + args=['folder', restorable_item.id])) + descendants = [] + + context = { + 'model_name': opts.verbose_name_plural, + 'media': self.media, + 'opts': opts, + 'app_label': opts.app_label, + 'current_item': filer_object, + 'current_item_type': filer_model, + 'descendants': descendants, + 'title': 'Restore %s %s' % ( + filer_model.capitalize(), str(filer_object)), + } + return render(request, 'admin/filer/trash/item_restore.html', context) + + def restore_items(self, request, filer_model, filer_obj_id): + filer_model_cls, filer_object = self._check_restore_view_valid( + request, filer_model, filer_obj_id) + + # should not allow view for items that do not have alive container + container_attr = 'folder' if filer_model == 'file' else 'parent' + container_id = getattr(filer_object, container_attr + '_id', None) + if container_id: + # Check if the container is alive (not trashed) using the alive manager + if not filer.models.Folder.objects.filter(id=container_id).exists(): + raise PermissionDenied + + if request.method == 'POST' and request.POST.get('post'): + filer_object.restore() + + if filer_model_cls is filer.models.Folder: + return redirect( + filer_object.get_admin_directory_listing_url_path()) + else: + if not filer_object.folder_id: + # clipboard files + return redirect('admin:filer-directory_listing-root') + return redirect(filer_object.get_admin_url_path()) + + raise PermissionDenied + + def file_check(self, request, file_id): + if not self.has_change_permission(request, None): + raise PermissionDenied + + try: + file_obj = filer.models.filemodels.File.trash.get(id=file_id) + except filer.models.filemodels.File.DoesNotExist as e: + raise Http404 + + data = {} + file_exists = file_obj.file.storage.exists(file_obj.file.name) + data['exists'] = file_exists + if file_exists: + # a bit of hack to force getting url even if it's in trash + file_obj.deleted_at = None + data['file_url'] = file_obj.url + return HttpResponse(json.dumps(data), content_type="application/json") + + def changelist_view(self, request, extra_context=None): + opts = self.model._meta + + if not self.has_change_permission(request, None): + raise PermissionDenied + + search_q = request.GET.get('q', '').split() + if search_q: + folder_q = reduce(operator.or_, + [Q(name__icontains=bit) for bit in search_q]) + files_q = reduce(operator.or_, + [Q(Q(name__icontains=bit) | + Q(original_filename__icontains=bit)) + for bit in search_q]) + + items = self.get_queryset(request) + paginator = Paginator(items, FILER_PAGINATE_BY) + + # Make sure page request is an int. If not, deliver first page. + try: + page = int(request.GET.get('page', '1')) + except ValueError: + page = 1 + + # If page request is out of range, deliver last page of results. + try: + paginated_items = paginator.page(page) + except (EmptyPage, InvalidPage): + paginated_items = paginator.page(paginator.num_pages) + + context = { + 'model_name': opts.verbose_name_plural, + 'media': self.media, + 'opts': opts, + 'app_label': opts.app_label, + 'paginator': paginator, + 'paginated_items': paginated_items, + 'search_string': request.GET.get('q', ''), + 'title': 'Deleted Files and Folders', + } + context.update(extra_context or {}) + return render(request, 'admin/filer/trash/directory_listing.html', context) diff --git a/filer/admin/views.py b/filer/admin/views.py new file mode 100644 index 000000000..265950ab1 --- /dev/null +++ b/filer/admin/views.py @@ -0,0 +1,155 @@ +from django import forms +from django.contrib import admin +from django.contrib.admin import widgets +from django.contrib.auth.decorators import login_required +from django.core.exceptions import PermissionDenied +from django.http import HttpResponseRedirect +from django.http.response import HttpResponseBadRequest +from django.template.response import TemplateResponse +from django.utils.translation import gettext_lazy as _ + +from .. import settings as filer_settings +from ..models import Clipboard, Folder, FolderRoot, tools +from ..admin.tools import AdminContext, admin_url_params_encoded, is_valid_destination, popup_status + + +class NewFolderForm(forms.ModelForm): + class Meta: + model = Folder + fields = ('name', 'site') + widgets = { + 'name': widgets.AdminTextInputWidget, + } + + def __init__(self, *args, **kwargs): + self.is_root_folder = kwargs.pop('is_root_folder', True) + super().__init__(*args, **kwargs) + if self.is_root_folder: + self.fields['site'].required = True + else: + # Hide site field for child folders + if 'site' in self.fields: + del self.fields['site'] + + def clean(self): + cleaned_data = super().clean() + if self.is_root_folder and not cleaned_data.get('site'): + raise forms.ValidationError('Site is required') + return cleaned_data + + +@login_required +def make_folder(request, folder_id=None): + if not folder_id: + folder_id = request.GET.get('parent_id') + if not folder_id: + folder_id = request.POST.get('parent_id') + if folder_id: + try: + folder = Folder.objects.get(id=folder_id) + except Folder.DoesNotExist: + raise PermissionDenied + else: + folder = None + + if folder and not folder.has_add_permission(request.user): + raise PermissionDenied + elif request.user.is_superuser: + pass + elif folder is None: + # regular users may not add root folders unless configured otherwise + if not filer_settings.FILER_ALLOW_REGULAR_USERS_TO_ADD_ROOT_FOLDERS: + raise PermissionDenied + elif not folder.has_add_children_permission(request): + # the user does not have the permission to add subfolders + raise PermissionDenied + + if request.method == 'POST': + new_folder_form = NewFolderForm(request.POST, is_root_folder=(folder is None)) + # Set parent on the instance before validation so model clean() works correctly + new_folder_form.instance.parent = folder + new_folder_form.instance.owner = request.user + if new_folder_form.is_valid(): + new_folder = new_folder_form.save(commit=False) + if (folder or FolderRoot()).contains_folder(new_folder.name): + new_folder_form._errors['name'] = new_folder_form.error_class( + [_('Folder with this name already exists.')]) + else: + new_folder.parent = folder + new_folder.owner = request.user + new_folder.save() + if popup_status(request): + context = admin.site.each_context(request) + return TemplateResponse(request, 'admin/filer/dismiss_popup.html', context) + else: + from django.urls import reverse + if folder: + url = reverse('admin:filer-directory_listing', kwargs={'folder_id': folder.id}) + else: + url = reverse('admin:filer-directory_listing-root') + return HttpResponseRedirect(url) + else: + new_folder_form = NewFolderForm(is_root_folder=(folder is None)) + + context = admin.site.each_context(request) + context.update({ + 'opts': Folder._meta, + 'new_folder_form': new_folder_form, + 'is_popup': popup_status(request), + 'filer_admin_context': AdminContext(request), + }) + return TemplateResponse(request, 'admin/filer/folder/new_folder_form.html', context) + + +@login_required +def paste_clipboard_to_folder(request): + + if request.method == 'POST': + folder_id = request.POST.get('folder_id') + if not folder_id: + raise PermissionDenied + try: + folder = Folder.objects.get(id=folder_id) + except Folder.DoesNotExist: + raise PermissionDenied + if not is_valid_destination(request, folder): + raise PermissionDenied + clipboard = Clipboard.objects.get(id=request.POST.get('clipboard_id')) + files_moved = tools.move_files_from_clipboard_to_folder(request, clipboard, folder) + tools.discard_clipboard_files(clipboard, files_moved) + redirect = request.GET.get('redirect_to', '') + if not redirect: + redirect = request.POST.get('redirect_to', '') + return HttpResponseRedirect( + '{}?order_by=-modified_at{}'.format( + redirect, + admin_url_params_encoded(request, first_separator='&'), + ) + ) + + +@login_required +def discard_clipboard(request): + if request.method == 'POST': + clipboard = Clipboard.objects.get(id=request.POST.get('clipboard_id')) + tools.discard_clipboard(clipboard) + return HttpResponseRedirect( + '{}{}'.format( + request.POST.get('redirect_to', ''), + admin_url_params_encoded(request, first_separator='&'), + ) + ) + + +@login_required +def delete_clipboard(request): + + if request.method == 'POST': + clipboard = Clipboard.objects.get(id=request.POST.get('clipboard_id')) + tools.delete_clipboard(clipboard) + return HttpResponseRedirect( + '{}{}'.format( + request.POST.get('redirect_to', ''), + admin_url_params_encoded(request, first_separator='&'), + ) + ) diff --git a/filer/apps.py b/filer/apps.py new file mode 100644 index 000000000..ce0dc38a1 --- /dev/null +++ b/filer/apps.py @@ -0,0 +1,69 @@ +import mimetypes + +from django.apps import AppConfig +from django.core.exceptions import ImproperlyConfigured +from django.utils.translation import gettext_lazy as _ + +from filer import __version__ as filer_version + + +class FilerConfig(AppConfig): + default_auto_field = 'django.db.models.AutoField' + name = 'filer' + verbose_name = _(f"Filer ({filer_version})") + + def register_optional_heif_supprt(self): + try: # pragma: no cover + from pillow_heif import register_heif_opener + + from .settings import IMAGE_EXTENSIONS, IMAGE_MIME_TYPES + + # Register with easy_thumbnails + register_heif_opener() + HEIF_EXTENSIONS = [".heic", ".heics", ".heif", ".heifs", ".hif"] + # Add extensions to python mimetypes which filer uses + for ext in HEIF_EXTENSIONS: + mimetypes.add_type("image/heic", ext) + # Mark them as images + IMAGE_EXTENSIONS += HEIF_EXTENSIONS + IMAGE_MIME_TYPES.append("heic") + except (ModuleNotFoundError, ImportError): + # No heif support installed + pass + + def resolve_validators(self): + """Resolve dotted path file validators""" + + import importlib + + from filer.settings import FILE_VALIDATORS, FILER_MIME_TYPE_WHITELIST + + if ( + not isinstance(FILER_MIME_TYPE_WHITELIST, (list, tuple)) or # noqa W504 + any(map(lambda x: not isinstance(x, str), FILER_MIME_TYPE_WHITELIST)) + ): # pragma: no cover + raise ImproperlyConfigured( + "filer: setting FILER_MIME_TYPE_WHITELIST needs to be a list or tuple of strings" + ) + self.MIME_TYPE_WHITELIST = FILER_MIME_TYPE_WHITELIST + self.FILE_VALIDATORS = {} + for mime_type, validators in FILE_VALIDATORS.items(): + functions = [] + for item in validators: + if callable(item): # pragma: no cover + functions.append(item) + else: + split = item.rsplit(".", 1) + try: + module = importlib.import_module(split[0]) + functions.append(getattr(module, split[-1])) + except (ImportError, ModuleNotFoundError, AttributeError): + raise ImproperlyConfigured(f"""filer: could not import validator "{item}".""") + self.FILE_VALIDATORS[mime_type] = functions + + def ready(self): + # Make webp mime type known to python (needed for python < 3.11) + mimetypes.add_type("image/webp", ".webp") + # + self.resolve_validators() + self.register_optional_heif_supprt() diff --git a/filer/cache.py b/filer/cache.py new file mode 100644 index 000000000..d9861ac60 --- /dev/null +++ b/filer/cache.py @@ -0,0 +1,91 @@ +import typing + +from django.core.cache import cache +from django.db.models import Model + + +UserModel = typing.TypeVar('UserModel', bound=Model) + + +def get_folder_perm_cache_key(user: UserModel, permission: str) -> str: + """ + Generates a unique cache key for a given user and permission. + + The key is a string in the format "filer:perm:", i.e. it does not + contain the user id. This will be sufficient for most use cases. + + Patch this method to include the user id in the cache key if necessary, e.g., + for far more than 1,000 admin users to make the cached unit require less memory. + + Parameters: + user (UserModel): The user for whom the cache key is being generated. + The `user` can be an instance of the default `django.contrib.auth.models.User` + or any custom user model specified by `AUTH_USER_MODEL` in the settings. + permission (str): The permission for which the cache key is being generated. + + Returns: + str: The generated cache key. + """ + return f"filer:perm:{permission}" + + +def get_folder_permission_cache(user: UserModel, permission: str) -> typing.Optional[typing.Set[int]]: + """ + Retrieves the cached folder permissions for a given user and permission. + + If the cache value exists, it returns the permissions for the user. + If the cache value does not exist, it returns None. + + Parameters: + user (UserModel): The user for whom the permissions are being retrieved. + The `user` can be an instance of the default `django.contrib.auth.models.User` + or any custom user model specified by `AUTH_USER_MODEL` in the settings. + permission (str): The permission for which the permissions are being retrieved. + + Returns: + set or None: The permissions for the user, or None if no cache value exists. + """ + cache_value = cache.get(get_folder_perm_cache_key(user, permission)) + if cache_value: + return cache_value.get(user.pk, None) + return None + + +def clear_folder_permission_cache(user: UserModel, permission: typing.Optional[str] = None) -> None: + """ + Clears the cached folder permissions for a given user. + + If a specific permission is provided, it clears the cache for that permission only. + If no specific permission is provided, it clears the cache for all permissions. + + Parameters: + user (UserModel): The user for whom the permissions are being cleared. + The `user` can be an instance of the default `django.contrib.auth.models.User` + or any custom user model specified by `AUTH_USER_MODEL` in the settings. + permission (str, optional): The specific permission to clear. Defaults to None. + """ + if permission is None: + for perm in ['can_read', 'can_edit', 'can_add_children']: + cache.delete(get_folder_perm_cache_key(user, perm)) + else: + cache.delete(get_folder_perm_cache_key(user, permission)) + + +def update_folder_permission_cache(user: UserModel, permission: str, id_list: typing.Set[int]) -> None: + """ + Updates the cached folder permissions for a given user and permission. + + It first retrieves the current permissions from the cache (or an empty dictionary if none exist). + Then it updates the permissions for the user with the provided list of IDs. + Finally, it sets the updated permissions back into the cache. + + Parameters: + user (UserModel): The user for whom the permissions are being updated. + The `user` can be an instance of the default `django.contrib.auth.models.User` + or any custom user model specified by `AUTH_USER_MODEL` in the settings. + permission (str): The permission to update. + id_list (set): The set of IDs to set as the new permissions. + """ + perms = cache.get(get_folder_perm_cache_key(user, permission)) or {} + perms[user.pk] = set(id_list) + cache.set(get_folder_perm_cache_key(user, permission), perms) diff --git a/filer/contrib/__init__.py b/filer/contrib/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/filer/contrib/clamav/__init__.py b/filer/contrib/clamav/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/filer/contrib/django_cms/__init__.py b/filer/contrib/django_cms/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/filer/contrib/django_cms/cms_toolbars.py b/filer/contrib/django_cms/cms_toolbars.py new file mode 100644 index 000000000..a42928dd2 --- /dev/null +++ b/filer/contrib/django_cms/cms_toolbars.py @@ -0,0 +1,51 @@ +from django.urls import reverse +from django.utils.encoding import force_str +from django.utils.translation import gettext_lazy as _ + +from cms.cms_toolbars import ADMIN_MENU_IDENTIFIER, ADMINISTRATION_BREAK +from cms.toolbar.items import Break +from cms.toolbar_base import CMSToolbar +from cms.toolbar_pool import toolbar_pool + + +SHORTCUTS_BREAK = 'Shortcuts Break' + + +@toolbar_pool.register +class FilerToolbar(CMSToolbar): + """ + Adds a Filer menu-item into django CMS's "ADMIN" (first) menu. + """ + @staticmethod + def get_insert_position(admin_menu, item_name): + """ + Ensures that there is a SHORTCUTS_BREAK and returns a position for an + alphabetical position against all items between SHORTCUTS_BREAK, and + the ADMINISTRATION_BREAK. + """ + start = admin_menu.find_first(Break, identifier=SHORTCUTS_BREAK) + if not start: + end = admin_menu.find_first(Break, identifier=ADMINISTRATION_BREAK) + admin_menu.add_break(SHORTCUTS_BREAK, position=end.index) + start = admin_menu.find_first(Break, identifier=SHORTCUTS_BREAK) + end = admin_menu.find_first(Break, identifier=ADMINISTRATION_BREAK) + + items = admin_menu.get_items()[start.index + 1: end.index] + for idx, item in enumerate(items): + try: + if force_str(item_name.lower()) < force_str(item.name.lower()): + return idx + start.index + 1 + except AttributeError: + # Some item types do not have a 'name' attribute. + pass + return end.index + + def populate(self): + media_library = _('Media library') + + admin_menu = self.toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER) + admin_menu.add_sideframe_item( + media_library, + url=reverse('admin:filer_folder_changelist'), + position=self.get_insert_position(admin_menu, media_library) + ) diff --git a/filer/fields/file.py b/filer/fields/file.py index abe589560..7fb4bf6b8 100644 --- a/filer/fields/file.py +++ b/filer/fields/file.py @@ -1,90 +1,101 @@ -#-*- coding: utf-8 -*- -import inspect +import logging +import warnings + from django import forms -from django.conf import settings as globalsettings -from django.contrib.admin.widgets import ForeignKeyRawIdWidget from django.contrib.admin.sites import site -from django.core.exceptions import ImproperlyConfigured -from django.core.urlresolvers import reverse +from django.contrib.admin.widgets import ForeignKeyRawIdWidget +from django.core.exceptions import ObjectDoesNotExist from django.db import models from django.template.loader import render_to_string +from django.urls import reverse +from django.utils.http import urlencode from django.utils.safestring import mark_safe -from django.utils.text import truncate_words -from filer.models import File -from filer import settings as filer_settings -import logging +from .. import settings as filer_settings +from ..models import File +from ..settings import ICON_CSS_LIB +from ..utils.compatibility import truncate_words +from ..utils.model_label import get_model_label + + logger = logging.getLogger(__name__) + class AdminFileWidget(ForeignKeyRawIdWidget): choices = None - def render(self, name, value, attrs=None): + def render(self, name, value, attrs=None, renderer=None): obj = self.obj_for_value(value) - css_id = attrs.get('id', 'id_image_x') - css_id_thumbnail_img = "%s_thumbnail_img" % css_id - css_id_description_txt = "%s_description_txt" % css_id + css_id = attrs.get("id", "id_image_x") related_url = None + change_url = "" if value: try: file_obj = File.objects.get(pk=value) - related_url = file_obj.logical_folder.\ - get_admin_directory_listing_url_path() - except Exception,e: + related_url = ( + file_obj.logical_folder.get_admin_directory_listing_url_path() + ) + change_url = file_obj.get_admin_change_url() + except Exception as e: # catch exception and manage it. We can re-raise it for debugging # purposes and/or just logging it, provided user configured # proper logging configuration if filer_settings.FILER_ENABLE_LOGGING: - logger.error('Error while rendering file widget: %s',e) + logger.error("Error while rendering file widget: %s", e) if filer_settings.FILER_DEBUG: - raise e + raise if not related_url: - related_url = reverse('admin:filer-directory_listing-root') + related_url = reverse("admin:filer-directory_listing-last") params = self.url_parameters() + params["_pick"] = "file" if params: - lookup_url = '?' + '&'.join( - ['%s=%s' % (k, v) for k, v in params.items()]) + lookup_url = "?" + urlencode(sorted(params.items())) else: - lookup_url = '' - if not 'class' in attrs: + lookup_url = "" + # Filer image is never autocomplete widget; Django's popup js fails if it finds "data-context="available-source" + self.attrs.pop("data-context", None) + if "class" not in attrs: # The JavaScript looks for this hook. - attrs['class'] = 'vForeignKeyRawIdAdminField' + attrs["class"] = "vForeignKeyRawIdAdminField" # rendering the super for ForeignKeyRawIdWidget on purpose here because # we only need the input and none of the other stuff that # ForeignKeyRawIdWidget adds hidden_input = super(ForeignKeyRawIdWidget, self).render( - name, value, attrs) - filer_static_prefix = filer_settings.FILER_STATICMEDIA_PREFIX - if not filer_static_prefix[-1] == '/': - filer_static_prefix += '/' + name, value, attrs + ) # grandparent super context = { - 'hidden_input': hidden_input, - 'lookup_url': '%s%s' % (related_url, lookup_url), - 'thumb_id': css_id_thumbnail_img, - 'span_id': css_id_description_txt, - 'object': obj, - 'lookup_name': name, - 'filer_static_prefix': filer_static_prefix, - 'clear_id': '%s_clear' % css_id, - 'id': css_id, + "hidden_input": hidden_input, + "lookup_url": f"{related_url}{lookup_url}", + "change_url": change_url, + "object": obj, + "lookup_name": name, + "id": css_id, + "admin_icon_delete": ("admin/img/icon-deletelink.svg"), } - html = render_to_string('admin/filer/widgets/admin_file.html', context) + html = render_to_string("admin/filer/widgets/admin_file.html", context) return mark_safe(html) def label_for_value(self, value): obj = self.obj_for_value(value) - return ' %s' % truncate_words(obj, 14) + return " %s" % truncate_words(obj, 14) def obj_for_value(self, value): - try: - key = self.rel.get_related_field().name - obj = self.rel.to._default_manager.get(**{key: value}) - except: + if value: + try: + # the next line may never bee reached + key = self.rel.get_related_field().name + obj = self.rel.model._default_manager.get(**{key: value}) + except ObjectDoesNotExist: + obj = None + else: obj = None return obj class Media: - js = (filer_settings.FILER_STATICMEDIA_PREFIX + 'js/popup_handling.js',) + css = { + "all": ("filer/css/admin_filer.css",) + ICON_CSS_LIB, + } + js = ("filer/js/dist/admin-file-widget.bundle.js",) class AdminFileFormField(forms.ModelChoiceField): @@ -96,12 +107,8 @@ def __init__(self, rel, queryset, to_field_name, *args, **kwargs): self.to_field_name = to_field_name self.max_value = None self.min_value = None - other_widget = kwargs.pop('widget', None) - if 'admin_site' in inspect.getargspec(self.widget.__init__)[0]: # Django 1.4 - widget_instance = self.widget(rel, site) - else: # Django <= 1.3 - widget_instance = self.widget(rel) - forms.Field.__init__(self, widget=widget_instance, *args, **kwargs) + kwargs.pop("widget", None) + super().__init__(queryset, widget=self.widget(rel, site), *args, **kwargs) def widget_attrs(self, widget): widget.required = self.required @@ -113,38 +120,26 @@ class FilerFileField(models.ForeignKey): default_model_class = File def __init__(self, **kwargs): - # we call ForeignKey.__init__ with the Image model as parameter... - # a FilerImageFiled can only be a ForeignKey to a Image - self.validate_related_name(kwargs.get('related_name', None)) - return super(FilerFileField, self).__init__( - self.default_model_class, **kwargs) - - def validate_related_name(self, name): - if not name: - return - if name and hasattr(self.default_model_class, name): - raise ImproperlyConfigured( - ("%s fields cannot have related name %r, this property " + \ - "already exists on %s") % (self.__class__.__name__, - name, - self.default_form_class.__name__) - ) + to = kwargs.pop("to", None) + dfl = get_model_label(self.default_model_class) + if to and get_model_label(to).lower() != dfl.lower(): + msg = "In {}: ForeignKey must point to {}; instead passed {}" + warnings.warn(msg.format(self.__class__.__name__, dfl, to), SyntaxWarning) + kwargs["to"] = dfl # hard-code `to` to model `filer.File` + super().__init__(**kwargs) def formfield(self, **kwargs): - # This is a fairly standard way to set up some defaults - # while letting the caller override them. defaults = { - 'form_class': self.default_form_class, - 'rel': self.rel, + "form_class": self.default_form_class, + "rel": self.remote_field, } defaults.update(kwargs) - return super(FilerFileField, self).formfield(**defaults) - - def south_field_triple(self): - "Returns a suitable description of this field for South." - # We'll just introspect ourselves, since we inherit. - from south.modelsinspector import introspector - field_class = "django.db.models.fields.related.ForeignKey" - args, kwargs = introspector(self) - # That's our definition! - return (field_class, args, kwargs) + return super().formfield(**defaults) + + +# PBS-specific: widget that doesn't show clear checkbox +from django.contrib.admin import widgets as django_widgets + + +class NonClearableFileInput(django_widgets.AdminFileWidget): + template_with_clear = '' diff --git a/filer/fields/folder.py b/filer/fields/folder.py index ad1475bd6..5a6dc450a 100644 --- a/filer/fields/folder.py +++ b/filer/fields/folder.py @@ -1,33 +1,35 @@ -#-*- coding: utf-8 -*- -from django.template.loader import render_to_string -import inspect +import warnings + from django import forms -from django.conf import settings -from django.contrib.admin.widgets import ForeignKeyRawIdWidget from django.contrib.admin.sites import site -from django.core.urlresolvers import reverse +from django.contrib.admin.widgets import ForeignKeyRawIdWidget +from django.core.exceptions import ObjectDoesNotExist from django.db import models +from django.template.loader import render_to_string +from django.urls import reverse +from django.utils.http import urlencode from django.utils.safestring import mark_safe -from django.utils.text import truncate_words -from django.utils.translation import ugettext as _ -from filer.models import Folder -from filer.settings import FILER_STATICMEDIA_PREFIX + +from ..models import Folder +from ..settings import ICON_CSS_LIB +from ..utils.compatibility import truncate_words +from ..utils.model_label import get_model_label class AdminFolderWidget(ForeignKeyRawIdWidget): choices = None - input_type = 'hidden' - is_hidden = True + input_type = "hidden" + is_hidden = False - def render(self, name, value, attrs=None): + def render(self, name, value, attrs=None, renderer=None): obj = self.obj_for_value(value) - css_id = attrs.get('id') + css_id = attrs.get("id") css_id_folder = "%s_folder" % css_id css_id_description_txt = "%s_description_txt" % css_id - required = self.attrs if attrs is None: attrs = {} related_url = None + if value: try: folder = Folder.objects.get(pk=value) @@ -35,52 +37,57 @@ def render(self, name, value, attrs=None): except Exception: pass if not related_url: - related_url = reverse('admin:filer-directory_listing-root') + related_url = reverse("admin:filer-directory_listing-last") params = self.url_parameters() - params['select_folder'] = 1 + params["_pick"] = "folder" if params: - url = '?' + '&'.join( - ['%s=%s' % (k, v) for k, v in params.items()]) + url = "?" + urlencode(sorted(params.items())) else: - url = '' - if not 'class' in attrs: + url = "" + if "class" not in attrs: # The JavaScript looks for this hook. - attrs['class'] = 'vForeignKeyRawIdAdminField' + attrs["class"] = "vForeignKeyRawIdAdminField" super_attrs = attrs.copy() hidden_input = super(ForeignKeyRawIdWidget, self).render( - name, value, super_attrs) + name, value, super_attrs + ) # grandparent super # TODO: "id_" is hard-coded here. This should instead use the correct # API to determine the ID dynamically. context = { - 'hidden_input': hidden_input, - 'lookup_url': '%s%s' % (related_url, url), - 'lookup_name': name, - 'span_id': css_id_description_txt, - 'object': obj, - 'clear_id': '%s_clear' % css_id, - 'descid': css_id_description_txt, - 'noimg': '%sicons/nofile_32x32.png' % FILER_STATICMEDIA_PREFIX, - 'foldid': css_id_folder, - 'id': css_id, - } - html = render_to_string('admin/filer/widgets/admin_folder.html', context) + "hidden_input": hidden_input, + "lookup_url": f"{related_url}{url}", + "lookup_name": name, + "span_id": css_id_description_txt, + "object": obj, + "clear_id": "%s_clear" % css_id, + "descid": css_id_description_txt, + "foldid": css_id_folder, + "id": css_id, + } + html = render_to_string("admin/filer/widgets/admin_folder.html", context) return mark_safe(html) def label_for_value(self, value): obj = self.obj_for_value(value) - return ' %s' % truncate_words(obj, 14) + return " %s" % truncate_words(obj, 14) def obj_for_value(self, value): + if not value: + return None try: key = self.rel.get_related_field().name - obj = self.rel.to._default_manager.get(**{key: value}) - except: + obj = self.rel.model._default_manager.get(**{key: value}) + except ObjectDoesNotExist: obj = None return obj class Media: - js = (FILER_STATICMEDIA_PREFIX + 'js/popup_handling.js',) + css = {"all": ("filer/css/admin_filer.css",) + ICON_CSS_LIB} + js = ( + "filer/js/addons/popup_handling.js", + "filer/js/widgets/admin-folder-widget.js", + ) class AdminFolderFormField(forms.ModelChoiceField): @@ -89,15 +96,13 @@ class AdminFolderFormField(forms.ModelChoiceField): def __init__(self, rel, queryset, to_field_name, *args, **kwargs): self.rel = rel self.queryset = queryset + self.limit_choices_to = kwargs.pop("limit_choices_to", None) self.to_field_name = to_field_name self.max_value = None self.min_value = None - kwargs.pop('widget', None) - if 'admin_site' in inspect.getargspec(self.widget.__init__)[0]: # Django 1.4 - widget_instance = self.widget(rel, site) - else: # Django <= 1.3 - widget_instance = self.widget(rel) - forms.Field.__init__(self, widget=widget_instance, *args, **kwargs) + kwargs.pop("widget", None) + kwargs.pop("blank", None) + forms.Field.__init__(self, widget=self.widget(rel, site), *args, **kwargs) def widget_attrs(self, widget): widget.required = self.required @@ -109,23 +114,22 @@ class FilerFolderField(models.ForeignKey): default_model_class = Folder def __init__(self, **kwargs): - return super(FilerFolderField, self).__init__(Folder, **kwargs) + # We hard-code the `to` argument for ForeignKey.__init__ + dfl = get_model_label(self.default_model_class) + if "to" in kwargs.keys(): # pragma: no cover + old_to = get_model_label(kwargs.pop("to")) + if old_to.lower() != dfl.lower(): + msg = "{} can only be a ForeignKey to {}; {} passed".format( + self.__class__.__name__, dfl, old_to + ) + warnings.warn(msg, SyntaxWarning) + kwargs["to"] = dfl + super().__init__(**kwargs) def formfield(self, **kwargs): - # This is a fairly standard way to set up some defaults - # while letting the caller override them. defaults = { - 'form_class': self.default_form_class, - 'rel': self.rel, + "form_class": self.default_form_class, + "rel": self.remote_field, } defaults.update(kwargs) - return super(FilerFolderField, self).formfield(**defaults) - - def south_field_triple(self): - "Returns a suitable description of this field for South." - # We'll just introspect ourselves, since we inherit. - from south.modelsinspector import introspector - field_class = "django.db.models.fields.related.ForeignKey" - args, kwargs = introspector(self) - # That's our definition! - return (field_class, args, kwargs) + return super().formfield(**defaults) diff --git a/filer/fields/image.py b/filer/fields/image.py index 6a2906014..d1ff162bb 100644 --- a/filer/fields/image.py +++ b/filer/fields/image.py @@ -1,7 +1,5 @@ -#-*- coding: utf-8 -*- -from filer.fields.file import AdminFileWidget, AdminFileFormField, \ - FilerFileField -from filer.models import Image +from .. import settings +from .file import AdminFileFormField, AdminFileWidget, FilerFileField class AdminImageWidget(AdminFileWidget): @@ -14,4 +12,4 @@ class AdminImageFormField(AdminFileFormField): class FilerImageField(FilerFileField): default_form_class = AdminImageFormField - default_model_class = Image + default_model_class = settings.FILER_IMAGE_MODEL diff --git a/filer/fields/multistorage_file.py b/filer/fields/multistorage_file.py index 8fd2d6bc9..83e73b5c9 100644 --- a/filer/fields/multistorage_file.py +++ b/filer/fields/multistorage_file.py @@ -1,10 +1,16 @@ -#-*- coding: utf-8 -*- -from django.core.files.base import File -from django.core.files.storage import Storage -from easy_thumbnails import fields as easy_thumbnails_fields, \ - files as easy_thumbnails_files -from filer import settings as filer_settings -from filer.utils.filer_easy_thumbnails import ThumbnailerNameMixin +import base64 +import hashlib +import warnings +from io import BytesIO + +from django.core.files.base import ContentFile +from django.db.models.fields.files import FileDescriptor + +from easy_thumbnails import fields as easy_thumbnails_fields +from easy_thumbnails import files as easy_thumbnails_files + +from .. import settings as filer_settings +from ..utils.filer_easy_thumbnails import ThumbnailerNameMixin STORAGES = { @@ -33,12 +39,38 @@ def generate_filename_multistorage(instance, filename): return upload_to +class MultiStorageFileDescriptor(FileDescriptor): + """ + This is rather similar to Django's ImageFileDescriptor. + It calls _data_changed on model instance when new + value is set. The callback is supposed to update fields which + are related to file data (like size, checksum, etc.). + When this is called from model __init__ (prev_assigned=False), + it does nothing because related fields might not have values yet. + In such case data_changed callback should be called at the end of model __init__ + (File.__init__ in this case). + """ + def __set__(self, instance, value): + prev_assigned = self.field.name in instance.__dict__ + previous_file = instance.__dict__.get(self.field.name) + super().__set__(instance, value) + + # To prevent recalculating file data related attributes when we are instantiating + # an object from the database, update only if the field had a value before this assignment. + # To prevent recalculating upon reassignment of the same file, update only if value is + # different from the previous one. + if prev_assigned and value != previous_file: + callback_attr = f'{self.field.name}_data_changed' + if hasattr(instance, callback_attr): + getattr(instance, callback_attr)() + + class MultiStorageFieldFile(ThumbnailerNameMixin, easy_thumbnails_files.ThumbnailerFieldFile): def __init__(self, instance, field, name): """ This is a little weird, but I couldn't find a better solution. - Thumbnailer.__init__ is called first for proper object inizialization. + Thumbnailer.__init__ is called first for proper object initialisation. Then we override some attributes defined at runtime with properties. We cannot simply call super().__init__ because filer Field objects doesn't have a storage attribute. @@ -83,20 +115,69 @@ def _thumbnail_base_dir(self): else: return self.thumbnail_options['private'].get('base_dir', '') + def get_thumbnail(self, thumbnail_options, save=True, generate=None): + # PBS: prevent thumbnail generation for soft-deleted (trashed) files + if hasattr(self.instance, 'is_in_trash') and self.instance.is_in_trash(): + return None + return super().get_thumbnail(thumbnail_options, save=save, generate=generate) + def save(self, name, content, save=True): - content.seek(0) # Ensure we upload the whole file - super(MultiStorageFieldFile, self).save(name, content, save) + content.seek(0) # Ensure we upload the whole file + super().save(name, content, save) + + def exists(self): + """ + Returns ``True`` if underlying file exists in storage. + """ + return self.name and self.storage.exists(self.name) class MultiStorageFileField(easy_thumbnails_fields.ThumbnailerField): attr_class = MultiStorageFieldFile + descriptor_class = MultiStorageFileDescriptor def __init__(self, verbose_name=None, name=None, storages=None, thumbnail_storages=None, thumbnail_options=None, **kwargs): + if 'upload_to' in kwargs: # pragma: no cover + upload_to = kwargs.pop("upload_to") + if upload_to != generate_filename_multistorage: + warnings.warn("MultiStorageFileField can handle only File objects;" + "%s passed" % upload_to, SyntaxWarning) self.storages = storages or STORAGES self.thumbnail_storages = thumbnail_storages or THUMBNAIL_STORAGES self.thumbnail_options = thumbnail_options or THUMBNAIL_OPTIONS super(easy_thumbnails_fields.ThumbnailerField, self).__init__( - verbose_name=verbose_name, name=name, - upload_to=generate_filename_multistorage, - storage=None, **kwargs) + verbose_name=verbose_name, name=name, + upload_to=generate_filename_multistorage, + storage=None, **kwargs) # grandparent super + + def value_to_string(self, obj): + value = super().value_to_string(obj) + if not filer_settings.FILER_DUMP_PAYLOAD: + return value + try: + payload_file = BytesIO(self.storage.open(value).read()) + sha = hashlib.sha1() + sha.update(payload_file.read()) + if sha.hexdigest() != obj.sha1: + warnings.warn('The checksum for "%s" diverges. Check for file consistency!' % obj.original_filename) + payload_file.seek(0) + encoded_string = base64.b64encode(payload_file.read()).decode('utf-8') + return value, encoded_string + except OSError: + warnings.warn(f'The payload for "{obj.original_filename}" is missing. No such file on disk: {self.storage.location}!') + return value + + def to_python(self, value): + if isinstance(value, list) and len(value) == 2 and isinstance(value[0], str): + filename, payload = value + try: + payload = base64.b64decode(payload) + except TypeError: + pass + else: + if self.storage.exists(filename): + self.storage.delete(filename) + self.storage.save(filename, ContentFile(payload)) + return filename + return value diff --git a/filer/locale/ar/LC_MESSAGES/django.mo b/filer/locale/ar/LC_MESSAGES/django.mo new file mode 100644 index 000000000..ec06f66ea Binary files /dev/null and b/filer/locale/ar/LC_MESSAGES/django.mo differ diff --git a/filer/locale/ar/LC_MESSAGES/django.po b/filer/locale/ar/LC_MESSAGES/django.po new file mode 100644 index 000000000..5469f0334 --- /dev/null +++ b/filer/locale/ar/LC_MESSAGES/django.po @@ -0,0 +1,1245 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Angelo Dini \n" +"Language-Team: Arabic (http://app.transifex.com/divio/django-filer/language/" +"ar/)\n" +"Language: ar\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "" + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "" + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "" + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "" + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "" + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "" + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "" + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "" + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "" + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "" + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "" + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "" + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "" + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "" + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "" + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "" + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "" + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "" + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "" + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "" + +#: models/abstract.py:91 +msgid "image" +msgstr "" + +#: models/abstract.py:92 +msgid "images" +msgstr "" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "" + +#: models/filemodels.py:116 +msgid "description" +msgstr "" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "" + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "" + +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:144 +msgid "URL copied to clipboard" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "" + +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" +#~ msgstr[2] "15c0f2d28d6dab1af1f6d94906beb627_pl_2" +#~ msgstr[3] "15c0f2d28d6dab1af1f6d94906beb627_pl_3" +#~ msgstr[4] "15c0f2d28d6dab1af1f6d94906beb627_pl_4" +#~ msgstr[5] "15c0f2d28d6dab1af1f6d94906beb627_pl_5" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/bg/LC_MESSAGES/django.mo b/filer/locale/bg/LC_MESSAGES/django.mo new file mode 100644 index 000000000..24974f0a5 Binary files /dev/null and b/filer/locale/bg/LC_MESSAGES/django.mo differ diff --git a/filer/locale/bg/LC_MESSAGES/django.po b/filer/locale/bg/LC_MESSAGES/django.po new file mode 100644 index 000000000..88b4a3899 --- /dev/null +++ b/filer/locale/bg/LC_MESSAGES/django.po @@ -0,0 +1,1224 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Angelo Dini \n" +"Language-Team: Bulgarian (http://app.transifex.com/divio/django-filer/" +"language/bg/)\n" +"Language: bg\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" + +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "" + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "" +msgstr[1] "" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "" + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "" + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "" + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "" + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "" + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "" + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "" + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "" + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "" + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "" + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "" + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "" + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "" + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "" + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "" + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "" + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "" + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "" + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "" + +#: models/abstract.py:91 +msgid "image" +msgstr "" + +#: models/abstract.py:92 +msgid "images" +msgstr "" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "" + +#: models/filemodels.py:116 +msgid "description" +msgstr "" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "" + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "" + +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "" +msgstr[1] "" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "" +msgstr[1] "" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:144 +msgid "URL copied to clipboard" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "" +msgstr[1] "" + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "" + +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/ca/LC_MESSAGES/django.mo b/filer/locale/ca/LC_MESSAGES/django.mo new file mode 100644 index 000000000..abddc6195 Binary files /dev/null and b/filer/locale/ca/LC_MESSAGES/django.mo differ diff --git a/filer/locale/ca/LC_MESSAGES/django.po b/filer/locale/ca/LC_MESSAGES/django.po new file mode 100644 index 000000000..4ba43842f --- /dev/null +++ b/filer/locale/ca/LC_MESSAGES/django.po @@ -0,0 +1,1261 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +# Roger Pons , 2013-2014,2016 +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Roger Pons , 2013-2014,2016\n" +"Language-Team: Catalan (http://app.transifex.com/divio/django-filer/language/" +"ca/)\n" +"Language: ca\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" + +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "" + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "Avançat" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "URL canònica" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" +"Cal seleccionar els elements en ordre per tal de realitzar accions sobre " +"ells. No s'ha modificat cap element." + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "%(total_count)s seleccionat" +msgstr[1] "Tots %(total_count)s seleccionats" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "0 de %(cnt)s seleccionats" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "No s'ha seleccionat cap acció." + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "S'han mogut %(count)d fitxers al portapapers." + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "Moure els fitxers seleccionats al portapapers." + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "S'han desactivat els permisos de %(count)d fitxers." + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "S'han activat els permisos de %(count)d fitxers." + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "Activar els permisos dels fitxers seleccionats" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "Desactivaer els permisos dels fitxers seleccionats" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "S'han esborrat %(count)d fitxers i/o carpetes." + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "No es poden esborrar els fitxers i/o carpetes" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "Esteu segur?" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "Esborrar fitxers i/o carpetes" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "Esborrar els fitxers i/o carpetes seleccionats" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "Ja existeixen carpetes amb els noms %s a la destinació seleccionada" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" +"S'han mogut %(count)d fitxers i/o carpetes a la carpeta '%(destination)s'" + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "Moure fitxers i/o carpetes" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "Moure els fitxers i/o carpetes seleccionats" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "S'ha canviat el nom de %(count)d fitxers." + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "Canviar el nom a fitxers" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" +"S'han copiat %(count)d fitxeres i/o carpetes a la carpeta '%(destination)s'." + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "Copiar fitxers i/o carpetes" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "Copiar els fitxers i/o carpetes seleccionats" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "S'han redimensionat %(count)d imatges." + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "Redimensionar imatges" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "Redimensionar les imatges seleccionades" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "Sufix que serà afegit als noms de fitxer dels fitxers copiats" + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "" +"El sufix ha de ser una part de nom de fitxer vàlida, simple i en minúscules, " +"com ara \"%(valid)s\"." + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "Format de renombrat amb valor de clau \"%(key)s\" desconegut." + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "Format de renombrat no vàlid: %(error)s" + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "opció de miniatures" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "ample" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "alçada" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "retallar" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "ampliar" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "Heu de triar una opció de miniatura o paràmetres de redimensionat." + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "Lloc del subjecte." + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "Ubicació del subjecte principal de l'escena. Format: \"x,y\"." + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "Foirmat erroni de la ubicació del subjecte." + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "La ubicació del subjecte està fora de la imatge." + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "La teva entrada: \"{subject_location}\"." + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "Ja existeix una carpeta amb aquest nom." + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "Filer" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "Biblioteca de medis." + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "text alternatiu per defecte" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "títol per defecte" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "lloc del subjecte" + +#: models/abstract.py:91 +msgid "image" +msgstr "imatge" + +#: models/abstract.py:92 +msgid "images" +msgstr "imatges" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "usuari" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "fitxers" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "portapapers" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "portapapers" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "fitxer" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "element del portapapers" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "elements del portapapers" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "carpeta" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "tamany del fitxer" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "sha1" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "té totes les dades obligatòries" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "nom de fitxer original" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "nom" + +#: models/filemodels.py:116 +msgid "description" +msgstr "descripció" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "propietari" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "pujat a" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "modificat a" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "Permisos desactivats" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" +"Desactiveu tots els permisos d'aquest fitxer. Aquest serà accessible de " +"forma pública per a tothom." + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "creat a" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "Carpeta" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "Carpetes" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "tots els elements" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "només aquest element" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "aquest elements i els seus fills" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "permetre" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "denegar" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "tipus" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "group" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "tothom" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "pot llegir" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "pot editar" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "pot afegir fills" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "permís de carpeta" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "permisos de carpeta" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "" + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "data agafada" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "autor" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "cal publicar sempre crèdits d'autor" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "cal publicar sempre els drets d'autor" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "ample en píxels." + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "alt en píxels" + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "opcions de miniatura" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "Pujades sense ordre" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "fitxer als que els falten metadades" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "arrel" + +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "Executar l'acció seleccionada" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "Anar" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "" +"Cliqueu aquí per seleccionar els objectes a través de totes les pàgines" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "Seleccionar tots els %(total_count)s fitixers i/o carpetes" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "Netejar la selecció" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "Tornar a la pàgina principal d'administració" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "Inici" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "Tornar a l'aplicació Filer" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "Tornar a la carpeta arrel" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "Tornar a la carpeta '%(folder_name)s'" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "Duplicats" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" +"Esborrar els fitxers seleccionats provocarà l'esborrar d'objectes " +"relacionats, però el teu compte no té permisos per esborrar els següents " +"tipus d'objectes:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "" +"Esborrer els fitxers i/o carpetes seleccionades provocarà l'esborrat dels " +"següents objectes protegits relacionats:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "" +"Segur que voleu esborrar els fitxers i/o carpetes seleccionades? Els " +"següents objectes i els seus elements relacionats seran esborrats:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "No, porta'm enrere." + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "Sí, estic segur" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "Història" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "Veure al lloc" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "Tornar a" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "pàgina principal d'administració" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "Icona de la carpeta" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." +msgstr "Sense permisos per copiar tots els fitxers i/o carpetes seleccionats." + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "Porta'm enrere" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "No hi ha carpetes de destí disponibles." + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "No hi ha fitxers i/o carpetes disponibles." + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "" +"Els següents fitxers i/o carpetes seran copiats a una carpeta de destí " +"(mantenint la seva estructura d'arbre):" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "Carpeta de destí:" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "Copiar" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "No està permès copiar fitxers a la mateixa carpeta" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "" +"El vostre compte no té permisos per redimensionar totes les imatges " +"seleccionades." + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "No hi ha imatges disponibles per redimensionar." + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "Les següents imatges seran redimensionades:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "" +"Trieu una opció de miniatura existent o especifiqueu paràmetres de " +"redimensionat:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "" +"Avís: les imatges seran redimensionades al mateix lloc i les originals es " +"perdran. Considereu realitzar abans una còpia d'aquestes per mantenir els " +"originals." + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "Redimensionar" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." +msgstr "" +"El vostre compte no té permisos per moure tots els fitxers i/o carpetes " +"seleccionats." + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "No hi ha fitxers i/o carpetes disponibles per moure." + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "" +"Els següents fitxers i/o carpetes seran moguts a una carpeta de destí " +"(mantenint la seva estructura d'arbre):" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "Moure" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "No està permès moure fitxers a la mateixa carpeta" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "" +"El vostre compte no té permisos per canviar el nom de tots els fitxers " +"seleccionats." + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "No hi ha fitxers per canviar el nom disponibles." + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "" +"En canviarà el nom dels següents fitxers (seguiran estant a les seves " +"carpetes i mantindran el seu nom de fitxers original, només serà modificat " +"el nom que es mostrarà):" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "Canviar el nom" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "Tornar a la carpeta pare" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "Modificar els detalls de la carpeta actual" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "Modificar" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "Cliqueu aquí per cercar la frase introduïda" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "Cercar" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "Tancar" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "Limitar" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "Marqueu per limitar la cercar a la carpeta actual" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "Limitar la cerca a la carpeta actual" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "Esborrar" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "Afegir una Carpeta nova" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "Carpeta nova" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "Pujar Arxius" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "Cal que abans seleccioneu una carpeta" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "Nom" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "Propietari" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "Mida" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "Acció" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "Modificar els detalls de la carpeta '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "%(counter)s fitxer" +msgstr[1] "%(counter)s fitxers" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "%(counter)s fitxer" +msgstr[1] "%(counter)s fitxers" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "Modifcar detalls de carpeta" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "Esborrar carpeta" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "Seleccionar aquest fitxer" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "Modificar els detalls de '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "Permisos" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "desactivat" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "activat" + +#: templates/admin/filer/folder/directory_table_list.html:144 +#, fuzzy +#| msgid "Move selected files to clipboard" +msgid "URL copied to clipboard" +msgstr "Moure els fitxers seleccionats al portapapers." + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "Esborrar fitxer" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "Deixeu anar fitxers aquí o utilitzeu el botó \"Pujar Fitxers\"" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "Deixeu anar el fitxer a pujar a:" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "Pujar" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "cancel·lar" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "Pujada correcta!" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "Pujada cancel·lada!" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "anterior" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "Pàgina %(number)s de %(num_pages)s." + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "següent" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "Seleccionar tots/es %(total_count)s" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "Afegir nou" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "Corregiu el següent error." +msgstr[1] "Corregiu els següents errors." + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "Desar" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "Portapapers" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "Enganxar aquí tots els elements" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "Moure tots els fitxer del portapapers a" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "Buidar Porta-retalls" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "el portapapers és buït" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "ha fallat la pujada" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "Tipus" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "MIda de fitxer" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "Modificat" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "Creat" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "trobat" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "i" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "cancel·lar la cerca" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "Netejar" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "o deixar anar aquí el fitxer" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "no s'ha seleccionat cap fitxer" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "Cercar" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "Escollir Fitxer" + +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/cs/LC_MESSAGES/django.mo b/filer/locale/cs/LC_MESSAGES/django.mo new file mode 100644 index 000000000..c73f2c7d9 Binary files /dev/null and b/filer/locale/cs/LC_MESSAGES/django.mo differ diff --git a/filer/locale/cs/LC_MESSAGES/django.po b/filer/locale/cs/LC_MESSAGES/django.po new file mode 100644 index 000000000..e56d59634 --- /dev/null +++ b/filer/locale/cs/LC_MESSAGES/django.po @@ -0,0 +1,1265 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +# Jakub Dorňák , 2020 +# Mirek Simek , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Jakub Dorňák , 2020\n" +"Language-Team: Czech (http://app.transifex.com/divio/django-filer/language/" +"cs/)\n" +"Language: cs\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n " +"<= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n" + +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "" + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "Pokročilé" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "kanonický odkaz" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "Nejdříve vyberte položku, která má být změněna." + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "Výpis složky %(folder_name)s" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "žádná položka z %(cnt)s není vybrána" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "Nebyla vybrána žádná operace." + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "Soubory (%(count)d) byly přesunuty do schránky." + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "Přesunout vybrané soubory do schránky" + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "Pro vybrané soubory (%(count)d) byla deaktivována oprávnění." + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "Pro vybrané soubory (%(count)d) byla aktivována oprávnění." + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "Aktivovat oprávnění pro vybrané soubory" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "Deaktivovat oprávnění pro vybrané soubory" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "Vybrané soubory a/nebo složky (%(count)d) byly smazány." + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "Nemohu smazat soubory a/nebo složky" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "Opravdu provést?" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "Smazat soubory a/nebo složky" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "Smazat vybrané soubory a/nebo složky" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "Složky pojmenované %s již v cílové složce existují" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" +"Vybrané soubory a/nebo složky (%(count)d) byly přesunuty do složky " +"'%(destination)s'." + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "Přesunout soubory a/nebo složky" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "Přesunout vybrané soubory a/nebo složky" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "Soubory (%(count)d) vyly přejmenovány." + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "Přejmenovat soubory" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" +"Soubory a/nebo složky (%(count)d) byly zkopírovány do složky " +"'%(destination)s'." + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "Kopírovat soubory a/nebo složky" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "Kopírovat vybrané soubory a/nebo složky" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "Velikost obrázků (%(count)d) byla změněna." + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "Změnit velikost obrázků" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "Změnit velikost vybraných obrázků" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "Koncovka, která bude přidána ke jménům kopírovaných souborů." + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "" +"Koncovka by měla být jednoduchá součást názvu souboru malými písmeny, " +"například \"%(valid)s\"." + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "Neznámý formát klíče pro přejmenování \"%(key)s\"." + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "Špatný formát přejmenování: %(error)s." + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "volby náhledu" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "šířka" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "výška" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "oříznout" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "zvětšit" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "" +"Musíte vybrat předdefinované volby náhledu nebo nastavit jednotlivé " +"parametry." + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "Pozice objektu" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "Pozice hlavního předmětu fotografie. Formát \"x,y\"." + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "Špatný formát pozice objektu. " + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "Zadaná pozice objektu je mimo obrázek. " + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "Vaše zadání: \"{subject_location}\". " + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "Složka s tímto názvem již existuje." + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "Správce souborů" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "Knihovna médií" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "výchozí alternativní text" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "výchozí popisek" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "poloha objektu" + +#: models/abstract.py:91 +msgid "image" +msgstr "obrázek" + +#: models/abstract.py:92 +msgid "images" +msgstr "obrázky" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "uživatel" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "soubory" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "schránka" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "schránky" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "soubor" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "položka schránky" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "položky schránky" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "složka" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "velikost souboru" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "sha1" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "má všechna povinná data" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "původní název souboru" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "název" + +#: models/filemodels.py:116 +msgid "description" +msgstr "popis" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "vlastník" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "nahráno" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "změněno" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "Oprávnění neaktivní" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" +"Deaktivovat veškerá oprávnění pro tento soubor. Soubor bude komukoli veřejně " +"dostupný." + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "vytvořeno" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "Složka" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "Složky" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "všechny položky" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "pouze tato položka" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "tato položka včetně všech potomků" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "povolit" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "zakázat" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "typ" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "skupina" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "kdokoli" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "smí číst" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "smí upravit" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "smí přidávat potomky" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "oprávnění složky" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "oprávnění složky" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "" + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "datum pořízení" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "autor" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "autor musí být vždy uveden" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "copyright musí být vždy uvedeno" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "šířka v pixelech." + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "výška v pixelech." + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "volby náhledu" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "Nezařazené" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "soubory s chybějícími informacemi" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "kořenová složka" + +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "Provést vybranou operaci" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "Provést" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "Klikněte sem pro výběr všechny položky na všech stránkách výpisu" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "Vybrat všechny soubory a/nebo složky (%(total_count)s)" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "Zrušit výběr" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "Přejít zpět na hlavní stránku administrace" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "Hlavní stránka" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "Přejít zpět do Správce souborů" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "Přejít zpět do kořenové složky" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "Přejít zpět do složky '%(folder_name)s'" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "Duplicity" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" +"Smazání vybraných souborů a/nebo složek bude mít za následek smazání všech " +"přidružených objektů, nicméně ke smazání následujících objektů nemáte " +"oprávnění:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "" +"Smazání vybraných souborů a/nebo složek bude mít za následek smazání " +"následujících přidružených objektů:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "" +"Opravdu chcete smazat vybrané soubory a složky? Všechny následující objekty " +"budou smazány:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "Ne, chci zpátky" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "Ano" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "Historie" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "Zobrazit na webu" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "Vrátit se do" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "hlavní stránka administrace" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "Ikona složky" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." +msgstr "Nemáte oprávnění kopírovat vybrané soubory a/nebo složky." + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "Zpět" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "Nejsou k dispozici žádné cílové složky." + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "Žádné soubory ani složky není možno kopírovat." + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "" +"Následující soubory a/nebo složky budou zkopírovány do cílové slžoky (jejich " +"stromová struktura bude zachována):" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "Cílová složka:" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "Kopírovat" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "Není možné kopírovat soubory do stejné složky" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "Nemáte oprávnění k změně velikosti vybraných obrázků." + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "Žádné obrázky ke změně velikosti." + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "Následujícím obrázkům bude změněna velikost:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "" +"Vyberte existující volby náhledu nebo zadejte parametry změny velikosti:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "" +"Varování: Bude změněna velikost obrázků a původní obrázky budou přepsány. " +"Pokud chcete zachovat obrázky v původní velikosti, nejdříve vytvořte jejich " +"kopie." + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "Změnit velikost" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." +msgstr "Nemáte oprávnění k přesunu vybraných souborů nebo složek." + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "Žádné soubory k přesunutí." + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "" +"Následující soubory a/nebo složky budou přesunyty do cílové složky (jejich " +"stromová struktura bude zachována)" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "Přesunout" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "Není možné přesouvat soubory do stejné složky" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "Nemáte oprávnění přejmenovat všechny vybrané soubory." + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "Žádné soubory k přejmenování." + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "" +"Následující soubory budou přejmenovány (změněno bude pouze zobrazované jméno)" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "Přejmenovat" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "Přejít zpět do nadřazené složky" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "Upravit aktuální složku" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "Upravit" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "Klikněte sem pro vyhledání zadaného výrazu" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "Hledat" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "Zavřít" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "Omezit" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "Zaškrtněte pro omezení hledání na aktuální složku" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "Omezit hledání na aktuální složku" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "Smazat" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "Přidá novou složku" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "Nová složka" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "Nahrát soubory" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "Nejdříve musíte vybrat složku" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "Název" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "Vlastník" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "Velikost" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "Akce" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "Upravit podrobnosti složky '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "Upravit podrobnosti složky" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "Smazat složku" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "Vybrat tento soubor" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "Upravit podrobnosti '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "Oprávnění" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "neaktivní" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "aktivní" + +#: templates/admin/filer/folder/directory_table_list.html:144 +#, fuzzy +#| msgid "Move selected files to clipboard" +msgid "URL copied to clipboard" +msgstr "Přesunout vybrané soubory do schránky" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "Kanonický odkaz '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "Stáhnout '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "Smazat soubor" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "Přetáhněte soubory sem nebo klikněte na tlačítko \"Nahrát soubory\"" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "Přetáhněte sem soubory, které chcete nahrát do:" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "Nahrát" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "zrušit" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "Nahrávání se zdařilo!" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "Nahrávání bylo zrušeno!" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "předchozí" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "Stránka %(number)s z %(num_pages)s." + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "následující" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "Vybrat všechny (%(total_count)s)" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "Přidat" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "Hlavní stránka administrace" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "Uložit" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "Schtánka" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "Vložit všechny položky sem" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "Přesunout všechny soubory ve schránce do" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "Vyprázdnit schránku" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "schránka je prázdná" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "nahrávání selhalo" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "Typ" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "Velikost souboru" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "Změněno" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "Vytvořeno" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "nalezeno" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "a" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "zrušit hledání" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "Vyčistit" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "přetáhněte soubory sem" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "žádný soubor nebyl vybrán" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "Vyhledat" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "Vybrat soubor" + +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" +#~ msgstr[2] "15c0f2d28d6dab1af1f6d94906beb627_pl_2" +#~ msgstr[3] "15c0f2d28d6dab1af1f6d94906beb627_pl_3" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/de/LC_MESSAGES/django.mo b/filer/locale/de/LC_MESSAGES/django.mo new file mode 100644 index 000000000..0f9415701 Binary files /dev/null and b/filer/locale/de/LC_MESSAGES/django.mo differ diff --git a/filer/locale/de/LC_MESSAGES/django.po b/filer/locale/de/LC_MESSAGES/django.po new file mode 100644 index 000000000..915585c65 --- /dev/null +++ b/filer/locale/de/LC_MESSAGES/django.po @@ -0,0 +1,1244 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +# Angelo Dini , 2016-2017 +# Fabian Braun , 2023 +# Jannik Vieten , 2016-2017 +# Mitja Martini , 2012 +# Mitja Martini , 2012 +# Peter Wischer , 2018 +# Stefan Foulis , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Fabian Braun , 2023\n" +"Language-Team: German (http://app.transifex.com/divio/django-filer/language/de/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: de\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: admin/clipboardadmin.py:17 +#| msgid "" +#| "ccount doesn't have permissions to rename all of the selected files." +msgid "You do not have permission to upload files." +msgstr "Du hast keine Berechtigungen, um Dateien hochzuladen." + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "Ich kann den Zielordner nicht finden. Bitter lade die Seite neu und versuche es noch einmal." + +#: admin/clipboardadmin.py:20 +msgid "" +"Can't use this folder, Permission Denied. Please select another folder." +msgstr "Zugriff auf diesen Ordner verweigert. Bitte wähle einen anderen Ordner." + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "Fortgeschritten" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "Kanonische URL" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "Einträge müssen ausgewählt werden, um Aktionen darauf auszuführen. Keine Einträge wurden geändert." + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "%(total_count)s ausgewählt" +msgstr[1] "Alle %(total_count)s ausgewählt" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "Verzeichnis Auflistung für %(folder_name)s" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "0 von %(cnt)s ausgewählt" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "Keine Aktion ausgewählt." + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "%(count)d Dateien wurden erfolgreich in die Zwischenablage gelegt." + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "Ausgewählte Dateien in die Zwischenablage legen" + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "Berechtigungen für %(count)d Dateien erfolgreich deaktiviert." + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "Berechtigungen für %(count)d Dateien erfolgreich aktiviert." + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "Berechtigungen für ausgewählte Dateien aktivieren" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "Berechtigungen für ausgewählte Dateien deaktivieren" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "%(count)d Dateien und/oder Ordner wurden erfolgreich gelöscht." + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "Dateien und/oder Ordner können nicht gelöscht werden" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "Bist Du sicher?" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "Lösche Dateien und/oder Ordner" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "Lösche ausgewählte Dateien und/oder Ordner" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "Die Ordner mit den Namen %s existieren bereits am ausgewählten Zielort" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "%(count)d Dateien und/oder Ordner wurden erfolgreich in den Ordner '%(destination)s' verschoben." + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "Verschiebe Dateien und/oder Ordner" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "Ausgewählte Dateien und/oder Ordner verschieben" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "%(count)d Dateien wurden erfolgreich umbenannt." + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "Dateien umbenennen" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "%(count)d Dateien und/oder Ordner wurden erfolgreich in den Ordner '%(destination)s' kopiert." + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "Kopiere Dateien und/oder Ordner" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "Ausgewählte Dateien und/oder Ordner kopieren" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "Die Bildgrösse von %(count)d Bildern wurde erfolgreich geändert." + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "Bildgrössen verändern" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "Die Bildgrössen der ausgewählten Bilder verändern" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "Die Dateiendung, welche an die Dateinamen der kopierten Dateien angehängt wird." + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "Die Dateiendung sollte ein gültiger, einfacher und kleingeschriebener Teil eines Dateinamens sein, wie zum Beispiel \"%(valid)s\"." + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "Unbekannter Schlüssel für das Umbenennungs-Format: %(key)s." + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "Ungültiges Umbenennungs-Format: %(error)s." + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "Vorschaubild Optionen" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "Breite" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "Höhe" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "Beschneiden" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "Vergrössern" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "Vorschaubild Optionen oder Parameter zur Grössenänderung müssen ausgewählt werden." + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "Ort des Hauptinhalts" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "Position des Hauptinhalts des Bildes. Format: \"x,y\"." + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "Ungültiges Format zur Positionsangabe." + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "Angegebene Position des Hauptinhalts liegt außerhalb des Bildes." + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "Deine Eingabe: \"{subject_location}\". " + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "Wer" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "Was" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "Dieser Ordnername wird bereits verwendet." + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "Filer" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "Medienbibliothek" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "Standard Alt-Text" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "Standard Bildlegende" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "Ort des Hauptinhalts" + +#: models/abstract.py:91 +msgid "image" +msgstr "Bild" + +#: models/abstract.py:92 +msgid "images" +msgstr "Bilder" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "Bildformat nicht erkannt oder Bildgröße überschreitet den Grenzwert von %(max_pixels)d Millionen Pixeln um einen Faktor 2 oder mehr. Vor erneutem Hochladen prüfen Sie das Dateiformat oder verkleinern Sie das Bild auf %(width)d x %(height)d oder weniger." + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "Bildgröße (%(pixels)d Millionen Pixel) überschreitet den Grenzwert von %(max_pixels)d Millionen Pixeln. Vor erneutem Hochladen verkleinern Sie das Bild auf %(width)d x %(height)d oder weniger." + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "Benutzer" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "Dateien" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "Zwischenablage" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "Zwischenablagen" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "Datei" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "Eintrag der Zwischenablage" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "Einträge der Zwischenablage" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "Ordner" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "Dateigrösse" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "sha1" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "hat alle Pflichtinhalte" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "ursprünglicher Dateiname" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "Name" + +#: models/filemodels.py:116 +msgid "description" +msgstr "Beschreibung" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "Besitzer" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "Hochgeladen am" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "Verändert am" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "Berechtigungen deaktiviert" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "Zugriffskontrolle für diese Datei deaktivieren. Die Datei wird für jeden öffentlich zugreifbar sein." + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "Übergeordneter Ordner" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "Angelegt am" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "Ordner" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "Ordner" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "alle Einträge" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "nur dieser Eintrag" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "dieser Eintrag und alle darunter liegenden Einträge" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "vererben" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "erlauben" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "verbieten" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "Typ" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "Gruppe" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "Jeder" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "kann lesen" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "kann ändern" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "kann Kinder hinzufügen" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "Ordnerberechtigung" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "Ordnerberechtigungen" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "Für den Typ \"Alle Einträge\" kann kein Ordner ausgewählt werden. " + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "Für alle Typen außer \"Alle Einträge\" muss ein Ordner ausgewählt werden." + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "Zusammen mit \"Jeder\" kann kein Benutzer oder eine Gruppe ausgewählt werden." + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "Mindestens ein Eintrag muss gewählt werden: \"Benutzer\", \"Gruppe\" oder \"Jeder\"." + +#: models/foldermodels.py:360 +#| msgid "Folders" +msgid "All Folders" +msgstr "Alle Ordner" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "Logischer Pfad" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "Nutzer: {user}" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "Gruppe: {group}" + +#: models/foldermodels.py:375 +#| msgid "everybody" +msgid "Everybody" +msgstr "Jede(r)" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "Edit" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "Lesen" + +#: models/foldermodels.py:390 +#| msgid "can add children" +msgid "Add children" +msgstr "Unterordner hinzufügen" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "Aufgenommen am" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "Autor" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "Nennung des Autoren ist Pflicht" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "Veröffentlichung des Copyright ist Pflicht" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "Breite in Pixel." + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "Höhe in Pixel." + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "Vorschaubild-Optionen" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "Nicht sortierte Uploads" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "Dateien mit fehlenden Metadaten" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "Start" + +#: settings.py:273 +msgid "Show table view" +msgstr "Tabellenansicht" + +#: settings.py:278 +#| msgid "thumbnail option" +msgid "Show thumbnail view" +msgstr "Vorschauansicht" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "Die ausgewählte Aktion ausführen" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "Los" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "Hier klicken, um die Objekte über alle Seiten hinweg auszuwählen" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "Alle %(total_count)s Dateien und/oder Ordner auswählen" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "Auswahl aufheben" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "Zur Admin Startseite zurück gehen" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "Startseite" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "Zur Filer App zurück gehen" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "Zum Root Ordner zurück gehen" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "Zum Ordner '%(folder_name)s' zurück gehen" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "Duplikate" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "Beim Löschen der ausgewählten Dateien und/oder Ordner, würden verbundene Objekte mitgelöscht. Dein Benutzerkonto hat jedoch nicht die erforderlichen Berechtigungen, um die folgenden Objekttypen zu löschen:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "Das Löschen der folgenden ausgewählten Dateien und/oder Ordner würde das Löschen der folgenden geschützten verknüpften Objekte erfordern:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "Bist Du sicher, dass Du die ausgewählten Dateien und/oder Ordner löschen willst? Alle der folgenden Objekte und ihre verbundenen Einträge werden gelöscht:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "Nein, zurück gehen" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "Ja, ich bin sicher" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "Historie" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "Auf der Website ansehen" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "Gehe zurück zu" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "Admin Startseite" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "Ordner Icon" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files " +"and/or folders." +msgstr "Dein Benutzerkonto hat nicht die Berechtigungen, um alle der ausgewählten Dateien und/oder Ordner zu kopieren." + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "Zurück gehen" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "Es gibt keine verwendbaren Zielordner." + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "Es gibt keine Dateien und/oder Ordner zum Kopieren." + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "Die folgenden Dateien und/oder Ordner werden in einen Zielordner kopiert (unter Beibehaltung ihrer Ordnerstruktur):" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "Zielordner" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "Kopieren" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "Es ist nicht erlaubt Dateien in den selben Ordner zu kopieren" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "Dein Benutzerkonto hat nicht die erforderlichen Berechtigungen, um die Grösse jedes der ausgewählten Bilder zu verändern." + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "Es gibt keine Bilder auf denen die Größenänderung anwendbar ist." + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "Die Grösse der folgenden Bilder wird verändert:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "Wähle eine vorhandene Vorschaubild Option aus oder gib die Parameter für die Bildgrössenänderung an:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "Warnung: Die Bilder werden in-place verändert. Die Originale gehen dabei verloren. Lege bei Bedarf eine Kopie der Originale an." + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "Bildgrösse verändern" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files " +"and/or folders." +msgstr "Dein Benutzerkonto hat nicht die erforderlichen Berechtigungen, um alle ausgewählten Dateien und/oder Ordner zu verschieben." + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "Es gibt keine verschiebbaren Dateien und/oder Ordner." + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "Die folgenden Dateien und/oder Ordner werden in ein Zielordner verschoben (unter Beibehaltung ihrer Ordnerstruktur):" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "Verschieben" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "Es ist nicht erlaubt Dateien in den selben Ordner zu verschieben" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "Dein Benutzerkonto hat nicht die erforderlichen Berechtigungen, um alle ausgewählten Dateien umzubenennen." + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "Es sind keine Dateien, die umbenannt werden können." + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "Die folgenden Dateien werden umbenannt (sie bleiben in ihren Ordnern und behalten ihren originalen Dateinamen, nur dier angezeigte Dateiname wird geändert):" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "Umbenennen" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "Gehe zurück zum übergeordneten Ordner" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "Details des aktuellen Ordners ändern" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "Ändern" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "Hier klicken, um nach dem eingegebenen Text zu suchen" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "Suchen" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "Schliessen" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "Limit" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "Aktivieren, um die Suche auf den aktuellen Ordner zu beschränken" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "Suche auf aktuellen Ordner beschränken" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "Löschen" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "Fügt einen neuen Ordner hinzu" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "Neuer Ordner" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "Dateien hochladen" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "Du musst zuerst einen Ordner auswählen" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "Name" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "Besitzer" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "Grösse" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "Aktion" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "Ändere Details des Ordners '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "%(counter)s Ordner" +msgstr[1] "%(counter)s Ordner" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "%(counter)s Datei" +msgstr[1] "%(counter)s Dateien" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "Ordner-Details ändern" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "Ordner löschen" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "Diese Datei auswählen" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "Ändere Details von '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "Berechtigungen" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "deaktiviert" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "aktiviert" + +#: templates/admin/filer/folder/directory_table_list.html:144 +#| msgid "Move selected files to clipboard" +msgid "URL copied to clipboard" +msgstr "URL in Zwischenablage kopiert" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +#| msgid "Change '%(item_label)s' details" +msgid "Canonical url '%(item_label)s'" +msgstr "Kanonische URL '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +#| msgid "Change '%(item_label)s' details" +msgid "Download '%(item_label)s'" +msgstr "'%(item_label)s' herunterladen" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "Datei löschen" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "Dateien hier ablegen oder den \"Datei hochladen\" Button benutzen." + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "Dateien hier ablegen um sie in den folgenden Ordner abzulegen:" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "Hochladen" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "Abbrechen" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "Upload erfolgreich!" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "Upload abgebrochen!" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "vorige" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "Seite %(number)s von %(num_pages)s." + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "nächste" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "Alle %(total_count)s auswählen" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +#| msgid "Select this file" +msgid "Select all" +msgstr "Alle auswählen" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +#| msgid "Filer" +msgid "Files" +msgstr "Dateien" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "Hinzufügen" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "Django Seiten-Administration" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "Bitte korrigiere den unten genannten Fehler." +msgstr[1] "Bitte korrigiere die unten genannten Fehler." + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "Sichern" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "Dein Browser unterstützt kein Audio." + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "Dein Browser unterstützt kein Video." + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "Zwischenablage" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "Alle Einträge hier einfügen" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "Bewege alle Dateien in der Zwischenablage nach" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "Zwischenablage leeren" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "die Zwischenablage ist leer" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "das Hochladen schlug fehl" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "Herunterladen" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "Vergrößern" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +#| msgid "file missing" +msgid "File is missing" +msgstr "Datei fehlt" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "Typ" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "Dateigrösse" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "Verändert am" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "Erstellt am" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "gefunden" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "und" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "Suche abbrechen" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "Zurücksetzen" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "oder die Datei hierhin ziehen" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "keine Datei ausgewählt" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "Nachschlagen" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "Datei auswählen" + +#: templates/admin/filer/widgets/admin_folder.html:16 +#| msgid "Choose File" +msgid "Choose Folder" +msgstr "Ordner auswählen" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "Datei \"{file_name}\": Die Sicherheitseinstellung der Seite haben die Datei zurückgewiesen." + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "Datei \"{file_name}\": Die Sicherheitseinstellung weisen {file_type}-Dateien zurück." + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "Datei \"{file_name}\": Die Sicherheitseinstellung weisen HTML-Dateien zurück." + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "Datei \"{file_name}\": Zurückgewiesen, da eine \"Cross Site Scripting\"-Attacke nicht ausgeschlossen werden kann." + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "Datei \"{file_name}\": SVG-Format nicht erkannt" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/en/LC_MESSAGES/django.mo b/filer/locale/en/LC_MESSAGES/django.mo index 24afa08d8..4f8792c06 100644 Binary files a/filer/locale/en/LC_MESSAGES/django.mo and b/filer/locale/en/LC_MESSAGES/django.mo differ diff --git a/filer/locale/en/LC_MESSAGES/django.po b/filer/locale/en/LC_MESSAGES/django.po index 8a0616881..fbcc67bdc 100644 --- a/filer/locale/en/LC_MESSAGES/django.po +++ b/filer/locale/en/LC_MESSAGES/django.po @@ -1,483 +1,643 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. # +# Translators: +# Translators: msgid "" msgstr "" -"Project-Id-Version: django-filer 0.9\n" +"Project-Id-Version: django Filer\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-07-13 19:10+0200\n" -"PO-Revision-Date: 2012-09-03 20:10+0100\n" -"Last-Translator: Stefan Foulis \n" -"Language-Team: en \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2016-06-17 14:16+0000\n" +"Last-Translator: Angelo Dini \n" +"Language-Team: English (http://www.transifex.com/divio/django-filer/language/" +"en/)\n" "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" -#: views.py:103 -msgid "Folder with this name already exists." +#: admin/clipboardadmin.py:17 +#, fuzzy +#| msgid "" +#| "Your account doesn't have permissions to rename all of the selected files." +msgid "You do not have permission to upload files." msgstr "" +"Your account doesn't have permissions to rename all of the selected files." -#: admin/fileadmin.py:41 -msgid "Advanced" +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" msgstr "" -#: admin/folderadmin.py:324 admin/folderadmin.py:427 +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "Advanced" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "canonical URL" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 msgid "" "Items must be selected in order to perform actions on them. No items have " "been changed." msgstr "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." -#: admin/folderadmin.py:344 +#: admin/folderadmin.py:434 #, python-format msgid "%(total_count)s selected" msgid_plural "All %(total_count)s selected" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%(total_count)s selected" +msgstr[1] "All %(total_count)s selected" -#: admin/folderadmin.py:377 +#: admin/folderadmin.py:460 #, python-format -msgid "0 of %(cnt)s selected" +msgid "Directory listing for %(folder_name)s" msgstr "" -#: admin/folderadmin.py:456 +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "0 of %(cnt)s selected" + +#: admin/folderadmin.py:612 msgid "No action selected." -msgstr "" +msgstr "No action selected." -#: admin/folderadmin.py:497 +#: admin/folderadmin.py:664 #, python-format msgid "Successfully moved %(count)d files to clipboard." -msgstr "" +msgstr "Successfully moved %(count)d files to clipboard." -#: admin/folderadmin.py:503 +#: admin/folderadmin.py:669 msgid "Move selected files to clipboard" -msgstr "" +msgstr "Move selected files to clipboard" -#: admin/folderadmin.py:537 +#: admin/folderadmin.py:709 #, python-format msgid "Successfully disabled permissions for %(count)d files." -msgstr "" +msgstr "Successfully disabled permissions for %(count)d files." -#: admin/folderadmin.py:541 +#: admin/folderadmin.py:711 #, python-format msgid "Successfully enabled permissions for %(count)d files." -msgstr "" +msgstr "Successfully enabled permissions for %(count)d files." -#: admin/folderadmin.py:550 +#: admin/folderadmin.py:719 msgid "Enable permissions for selected files" -msgstr "" +msgstr "Enable permissions for selected files" -#: admin/folderadmin.py:555 +#: admin/folderadmin.py:725 msgid "Disable permissions for selected files" -msgstr "" +msgstr "Disable permissions for selected files" -#: admin/folderadmin.py:623 +#: admin/folderadmin.py:789 #, python-format msgid "Successfully deleted %(count)d files and/or folders." -msgstr "" +msgstr "Successfully deleted %(count)d files and/or folders." -#: admin/folderadmin.py:630 +#: admin/folderadmin.py:794 msgid "Cannot delete files and/or folders" -msgstr "" +msgstr "Cannot delete files and/or folders" -#: admin/folderadmin.py:632 +#: admin/folderadmin.py:796 msgid "Are you sure?" -msgstr "" +msgstr "Are you sure?" -#: admin/folderadmin.py:637 +#: admin/folderadmin.py:802 msgid "Delete files and/or folders" -msgstr "" +msgstr "Delete files and/or folders" -#: admin/folderadmin.py:656 +#: admin/folderadmin.py:823 msgid "Delete selected files and/or folders" -msgstr "" +msgstr "Delete selected files and/or folders" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "Folders with names %s already exist at the selected destination" -#: admin/folderadmin.py:771 +#: admin/folderadmin.py:934 #, python-format msgid "" "Successfully moved %(count)d files and/or folders to folder " "'%(destination)s'." msgstr "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." -#: admin/folderadmin.py:778 admin/folderadmin.py:780 +#: admin/folderadmin.py:942 admin/folderadmin.py:944 msgid "Move files and/or folders" -msgstr "" +msgstr "Move files and/or folders" -#: admin/folderadmin.py:797 +#: admin/folderadmin.py:959 msgid "Move selected files and/or folders" -msgstr "" +msgstr "Move selected files and/or folders" -#: admin/folderadmin.py:854 +#: admin/folderadmin.py:1016 #, python-format msgid "Successfully renamed %(count)d files." -msgstr "" +msgstr "Successfully renamed %(count)d files." -#: admin/folderadmin.py:862 admin/folderadmin.py:864 admin/folderadmin.py:881 +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 msgid "Rename files" -msgstr "" +msgstr "Rename files" -#: admin/folderadmin.py:975 +#: admin/folderadmin.py:1137 #, python-format msgid "" "Successfully copied %(count)d files and/or folders to folder " "'%(destination)s'." msgstr "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." -#: admin/folderadmin.py:989 admin/folderadmin.py:991 +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 msgid "Copy files and/or folders" -msgstr "" +msgstr "Copy files and/or folders" -#: admin/folderadmin.py:1010 +#: admin/folderadmin.py:1174 msgid "Copy selected files and/or folders" -msgstr "" +msgstr "Copy selected files and/or folders" -#: admin/folderadmin.py:1105 +#: admin/folderadmin.py:1279 #, python-format msgid "Successfully resized %(count)d images." -msgstr "" +msgstr "Successfully resized %(count)d images." -#: admin/folderadmin.py:1113 admin/folderadmin.py:1115 +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 msgid "Resize images" -msgstr "" +msgstr "Resize images" -#: admin/folderadmin.py:1133 +#: admin/folderadmin.py:1303 msgid "Resize selected images" -msgstr "" +msgstr "Resize selected images" -#: admin/forms.py:26 +#: admin/forms.py:24 msgid "Suffix which will be appended to filenames of copied files." -msgstr "" +msgstr "Suffix which will be appended to filenames of copied files." -#: admin/forms.py:33 +#: admin/forms.py:31 #, python-format msgid "" "Suffix should be a valid, simple and lowercase filename part, like " "\"%(valid)s\"." msgstr "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." -#: admin/forms.py:54 +#: admin/forms.py:52 #, python-format msgid "Unknown rename format value key \"%(key)s\"." -msgstr "" +msgstr "Unknown rename format value key \"%(key)s\"." -#: admin/forms.py:56 +#: admin/forms.py:54 #, python-format msgid "Invalid rename format: %(error)s." -msgstr "" +msgstr "Invalid rename format: %(error)s." -#: admin/forms.py:62 +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 msgid "thumbnail option" -msgstr "" +msgstr "thumbnail option" -#: admin/forms.py:63 +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 msgid "width" -msgstr "" +msgstr "width" -#: admin/forms.py:64 +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 msgid "height" -msgstr "" +msgstr "height" -#: admin/forms.py:65 +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 msgid "crop" -msgstr "" +msgstr "crop" -#: admin/forms.py:66 +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 msgid "upscale" -msgstr "" +msgstr "upscale" -#: admin/forms.py:71 +#: admin/forms.py:79 msgid "Thumbnail option or resize parameters must be choosen." +msgstr "Thumbnail option or resize parameters must be choosen." + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "Subject location" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "Location of the main subject of the scene. Format: \"x,y\"." + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "Invalid subject location format. " + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "Subject location is outside of the image. " + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "Your input: \"{subject_location}\". " + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" msgstr "" -#: admin/forms.py:73 -msgid "Resize parameters must be choosen." +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" msgstr "" -#: admin/imageadmin.py:12 -msgid "Subject location" +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "Folder with this name already exists." + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "Filer" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" msgstr "" -#: admin/imageadmin.py:13 -msgid "Location of the main subject of the scene." +#: models/abstract.py:62 +msgid "default alt text" +msgstr "default alt text" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "default caption" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "subject location" + +#: models/abstract.py:91 +msgid "image" +msgstr "image" + +#: models/abstract.py:92 +msgid "images" +msgstr "images" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." msgstr "" -#: models/clipboardmodels.py:9 models/foldermodels.py:236 -msgid "user" +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." msgstr "" -#: models/clipboardmodels.py:11 models/filemodels.py:287 +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "user" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 msgid "files" -msgstr "" +msgstr "files" -#: models/clipboardmodels.py:34 models/clipboardmodels.py:40 +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 msgid "clipboard" -msgstr "" +msgstr "clipboard" -#: models/clipboardmodels.py:35 +#: models/clipboardmodels.py:25 msgid "clipboards" -msgstr "" +msgstr "clipboards" -#: models/clipboardmodels.py:39 models/filemodels.py:35 -#: models/filemodels.py:286 +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 msgid "file" -msgstr "" +msgstr "file" -#: models/clipboardmodels.py:44 +#: models/clipboardmodels.py:56 msgid "clipboard item" -msgstr "" +msgstr "clipboard item" -#: models/clipboardmodels.py:45 +#: models/clipboardmodels.py:57 msgid "clipboard items" -msgstr "" +msgstr "clipboard items" -#: models/filemodels.py:33 templates/admin/filer/folder/change_form.html:9 -#: templates/admin/filer/folder/directory_listing.html:74 +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 #: templates/admin/filer/folder/new_folder_form.html:4 -#: templates/admin/filer/tools/clipboard/clipboard.html:26 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 msgid "folder" -msgstr "" +msgstr "folder" -#: models/filemodels.py:36 +#: models/filemodels.py:81 msgid "file size" -msgstr "" +msgstr "file size" -#: models/filemodels.py:38 +#: models/filemodels.py:87 msgid "sha1" -msgstr "" +msgstr "sha1" -#: models/filemodels.py:40 +#: models/filemodels.py:94 msgid "has all mandatory data" -msgstr "" +msgstr "has all mandatory data" -#: models/filemodels.py:42 +#: models/filemodels.py:100 msgid "original filename" -msgstr "" +msgstr "original filename" -#: models/filemodels.py:44 models/foldermodels.py:99 +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 msgid "name" -msgstr "" +msgstr "name" -#: models/filemodels.py:46 +#: models/filemodels.py:116 msgid "description" -msgstr "" +msgstr "description" -#: models/filemodels.py:50 +#: models/filemodels.py:125 models/foldermodels.py:108 msgid "owner" -msgstr "" +msgstr "owner" -#: models/filemodels.py:52 models/foldermodels.py:105 +#: models/filemodels.py:129 models/foldermodels.py:116 msgid "uploaded at" -msgstr "" +msgstr "uploaded at" -#: models/filemodels.py:53 models/foldermodels.py:108 +#: models/filemodels.py:134 models/foldermodels.py:126 msgid "modified at" -msgstr "" +msgstr "modified at" -#: models/filemodels.py:57 +#: models/filemodels.py:140 msgid "Permissions disabled" +msgstr "Permissions disabled" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." msgstr "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." -#: models/filemodels.py:58 -msgid "Disable any permission checking for this " +#: models/foldermodels.py:94 +msgid "parent" msgstr "" -#: models/foldermodels.py:107 +#: models/foldermodels.py:121 msgid "created at" -msgstr "" +msgstr "created at" -#: models/foldermodels.py:211 -#: templates/admin/filer/widgets/admin_folder.html:3 -#: templates/admin/filer/widgets/admin_folder.html:5 +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 msgid "Folder" -msgstr "" +msgstr "Folder" -#: models/foldermodels.py:212 +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 msgid "Folders" -msgstr "" +msgstr "Folders" -#: models/foldermodels.py:227 +#: models/foldermodels.py:260 msgid "all items" -msgstr "" +msgstr "all items" -#: models/foldermodels.py:228 +#: models/foldermodels.py:261 msgid "this item only" -msgstr "" +msgstr "this item only" -#: models/foldermodels.py:229 +#: models/foldermodels.py:262 msgid "this item and all children" +msgstr "this item and all children" + +#: models/foldermodels.py:266 +msgid "inherit" msgstr "" -#: models/foldermodels.py:233 +#: models/foldermodels.py:267 +msgid "allow" +msgstr "allow" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "deny" + +#: models/foldermodels.py:280 msgid "type" -msgstr "" +msgstr "type" -#: models/foldermodels.py:239 +#: models/foldermodels.py:297 msgid "group" -msgstr "" +msgstr "group" -#: models/foldermodels.py:240 +#: models/foldermodels.py:304 msgid "everybody" -msgstr "" - -#: models/foldermodels.py:242 -msgid "can edit" -msgstr "" +msgstr "everybody" -#: models/foldermodels.py:243 +#: models/foldermodels.py:309 msgid "can read" -msgstr "" +msgstr "can read" -#: models/foldermodels.py:244 +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "can edit" + +#: models/foldermodels.py:325 msgid "can add children" -msgstr "" +msgstr "can add children" -#: models/foldermodels.py:273 +#: models/foldermodels.py:333 msgid "folder permission" -msgstr "" +msgstr "folder permission" -#: models/foldermodels.py:274 +#: models/foldermodels.py:334 msgid "folder permissions" -msgstr "" +msgstr "folder permissions" -#: models/imagemodels.py:39 -msgid "date taken" +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." msgstr "" -#: models/imagemodels.py:42 -msgid "default alt text" +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." msgstr "" -#: models/imagemodels.py:43 -msgid "default caption" +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." msgstr "" -#: models/imagemodels.py:45 templates/image_filer/image.html:6 -msgid "author" +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." msgstr "" -#: models/imagemodels.py:47 -msgid "must always publish author credit" -msgstr "" +#: models/foldermodels.py:360 +#, fuzzy +#| msgid "Folders" +msgid "All Folders" +msgstr "Folders" -#: models/imagemodels.py:48 -msgid "must always publish copyright" +#: models/foldermodels.py:362 +msgid "Logical Path" msgstr "" -#: models/imagemodels.py:50 -msgid "subject location" +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" msgstr "" -#: models/imagemodels.py:200 -msgid "image" +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" msgstr "" -#: models/imagemodels.py:201 -msgid "images" +#: models/foldermodels.py:375 +#, fuzzy +#| msgid "everybody" +msgid "Everybody" +msgstr "everybody" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" msgstr "" -#: models/virtualitems.py:45 -#: templates/admin/filer/tools/clipboard/clipboard.html:26 -msgid "unfiled files" +#: models/foldermodels.py:389 +msgid "Read" msgstr "" -#: models/virtualitems.py:59 +#: models/foldermodels.py:390 +#, fuzzy +#| msgid "can add children" +msgid "Add children" +msgstr "can add children" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "date taken" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "author" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "must always publish author credit" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "must always publish copyright" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "width in pixel." + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "height in pixel." + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "thumbnail options" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "Unsorted Uploads" + +#: models/virtualitems.py:73 msgid "files with missing metadata" -msgstr "" +msgstr "files with missing metadata" -#: models/virtualitems.py:73 templates/admin/filer/breadcrumbs.html:6 -#: templates/admin/filer/folder/change_form.html:9 -#: templates/admin/filer/folder/directory_listing.html:74 -#: templates/image_filer/image_export_form.html:10 +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 msgid "root" +msgstr "root" + +#: settings.py:273 +msgid "Show table view" msgstr "" -#: templates/admin/filer/actions.html:4 +#: settings.py:278 +#, fuzzy +#| msgid "thumbnail option" +msgid "Show thumbnail view" +msgstr "thumbnail option" + +#: templates/admin/filer/actions.html:5 msgid "Run the selected action" -msgstr "" +msgstr "Run the selected action" -#: templates/admin/filer/actions.html:4 +#: templates/admin/filer/actions.html:5 msgid "Go" -msgstr "" +msgstr "Go" -#: templates/admin/filer/actions.html:11 +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 msgid "Click here to select the objects across all pages" -msgstr "" +msgstr "Click here to select the objects across all pages" -#: templates/admin/filer/actions.html:11 +#: templates/admin/filer/actions.html:14 #, python-format msgid "Select all %(total_count)s files and/or folders" -msgstr "" +msgstr "Select all %(total_count)s files and/or folders" -#: templates/admin/filer/actions.html:13 +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 msgid "Clear selection" -msgstr "" +msgstr "Clear selection" #: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 msgid "Go back to admin homepage" -msgstr "" +msgstr "Go back to admin homepage" #: templates/admin/filer/breadcrumbs.html:4 -#: templates/admin/filer/folder/change_form.html:7 -#: templates/image_filer/image_export_form.html:7 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 msgid "Home" -msgstr "" +msgstr "Home" #: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 msgid "Go back to Filer app" -msgstr "" - -#: templates/admin/filer/breadcrumbs.html:5 -#: templates/admin/filer/folder/change_form.html:8 -#: templates/image_filer/image_export_form.html:8 -msgid "Filer" -msgstr "" +msgstr "Go back to Filer app" #: templates/admin/filer/breadcrumbs.html:6 -#: templates/image_filer/image_export_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:35 msgid "Go back to root folder" -msgstr "" +msgstr "Go back to root folder" #: templates/admin/filer/breadcrumbs.html:8 -#: templates/admin/filer/breadcrumbs.html:11 -#: templates/admin/filer/folder/change_form.html:11 -#: templates/image_filer/image_export_form.html:12 -#: templates/image_filer/image_export_form.html:14 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 #, python-format msgid "Go back to '%(folder_name)s' folder" -msgstr "" - -#: templates/admin/filer/change_form.html:28 -msgid "duplicates" -msgstr "" - -#: templates/admin/filer/delete_confirmation.html:13 -#, python-format -msgid "" -"Deleting the %(object_name)s '%(escaped_object)s' would result in deleting " -"related objects, but your account doesn't have permission to delete the " -"following types of objects:" -msgstr "" +msgstr "Go back to '%(folder_name)s' folder" -#: templates/admin/filer/delete_confirmation.html:21 -#, python-format -msgid "" -"Deleting the %(object_name)s '%(escaped_object)s' would require deleting the " -"following protected related objects:" -msgstr "" - -#: templates/admin/filer/delete_confirmation.html:29 -#, python-format -msgid "" -"Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? " -"All of the following related items will be deleted:" -msgstr "" - -#: templates/admin/filer/delete_confirmation.html:34 -#: templates/admin/filer/delete_selected_files_confirmation.html:45 -msgid "Yes, I'm sure" -msgstr "" +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "Duplicates" #: templates/admin/filer/delete_selected_files_confirmation.html:11 msgid "" @@ -485,399 +645,636 @@ msgid "" "objects, but your account doesn't have permission to delete the following " "types of objects:" msgstr "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" #: templates/admin/filer/delete_selected_files_confirmation.html:19 msgid "" "Deleting the selected files and/or folders would require deleting the " "following protected related objects:" msgstr "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" #: templates/admin/filer/delete_selected_files_confirmation.html:27 msgid "" "Are you sure you want to delete the selected files and/or folders? All of " "the following objects and their related items will be deleted:" msgstr "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" -#: templates/admin/filer/folder/change_form.html:7 -#: templates/admin/filer/folder/change_form.html:8 -#: templates/admin/filer/folder/change_form.html:9 -#: templates/admin/filer/folder/directory_listing.html:74 -#: templates/image_filer/image_export_form.html:7 -#: templates/image_filer/image_export_form.html:8 -#: templates/image_filer/image_export_form.html:16 -msgid "Go back to" -msgstr "" +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "No, take me back" -#: templates/admin/filer/folder/change_form.html:7 -#: templates/image_filer/image_export_form.html:7 -msgid "admin homepage" -msgstr "" +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "Yes, I'm sure" -#: templates/admin/filer/folder/change_form.html:22 -#: templates/admin/filer/image/change_form.html:9 +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 msgid "History" -msgstr "" +msgstr "History" +#: templates/admin/filer/file/change_form.html:37 #: templates/admin/filer/folder/change_form.html:23 -#: templates/admin/filer/image/change_form.html:10 +#: templates/admin/filer/image/change_form.html:37 msgid "View on site" -msgstr "" +msgstr "View on site" -#: templates/admin/filer/folder/change_form.html:35 -#: templates/admin/filer/folder/directory_listing.html:75 -#: templates/admin/filer/folder/directory_listing.html:85 -#: templates/admin/filer/folder/directory_table.html:23 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "Go back to" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "admin homepage" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 msgid "Folder Icon" -msgstr "" +msgstr "Folder Icon" -#: templates/admin/filer/folder/choose_copy_destination.html:12 +#: templates/admin/filer/folder/choose_copy_destination.html:23 msgid "" "Your account doesn't have permissions to copy all of the selected files and/" "or folders." msgstr "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." -#: templates/admin/filer/folder/choose_copy_destination.html:15 -#: templates/admin/filer/folder/choose_move_destination.html:15 +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "Take me back" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 msgid "There are no destination folders available." -msgstr "" +msgstr "There are no destination folders available." -#: templates/admin/filer/folder/choose_copy_destination.html:18 +#: templates/admin/filer/folder/choose_copy_destination.html:35 msgid "There are no files and/or folders available to copy." -msgstr "" +msgstr "There are no files and/or folders available to copy." -#: templates/admin/filer/folder/choose_copy_destination.html:20 +#: templates/admin/filer/folder/choose_copy_destination.html:40 msgid "" "The following files and/or folders will be copied to a destination folder " "(retaining their tree structure):" msgstr "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" -#: templates/admin/filer/folder/choose_copy_destination.html:32 -#: templates/admin/filer/folder/choose_move_destination.html:32 +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 msgid "Destination folder:" -msgstr "" +msgstr "Destination folder:" -#: templates/admin/filer/folder/choose_copy_destination.html:39 +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 msgid "Copy" -msgstr "" +msgstr "Copy" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "It is not allowed to copy files into same folder" -#: templates/admin/filer/folder/choose_images_resize_options.html:12 +#: templates/admin/filer/folder/choose_images_resize_options.html:15 msgid "" "Your account doesn't have permissions to resize all of the selected images." msgstr "" +"Your account doesn't have permissions to resize all of the selected images." -#: templates/admin/filer/folder/choose_images_resize_options.html:15 +#: templates/admin/filer/folder/choose_images_resize_options.html:18 msgid "There are no images available to resize." -msgstr "" +msgstr "There are no images available to resize." -#: templates/admin/filer/folder/choose_images_resize_options.html:17 +#: templates/admin/filer/folder/choose_images_resize_options.html:20 msgid "The following images will be resized:" -msgstr "" - -#: templates/admin/filer/folder/choose_images_resize_options.html:30 -msgid "Choose an existing thumbnail option or enter resize parameters:" -msgstr "" +msgstr "The following images will be resized:" #: templates/admin/filer/folder/choose_images_resize_options.html:32 -msgid "Choose resize parameters:" -msgstr "" +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "Choose an existing thumbnail option or enter resize parameters:" -#: templates/admin/filer/folder/choose_images_resize_options.html:35 +#: templates/admin/filer/folder/choose_images_resize_options.html:36 msgid "" "Warning: Images will be resized in-place and originals will be lost. Maybe " "first make a copy of them to retain the originals." msgstr "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." -#: templates/admin/filer/folder/choose_images_resize_options.html:36 +#: templates/admin/filer/folder/choose_images_resize_options.html:39 msgid "Resize" -msgstr "" +msgstr "Resize" -#: templates/admin/filer/folder/choose_move_destination.html:12 +#: templates/admin/filer/folder/choose_move_destination.html:35 msgid "" "Your account doesn't have permissions to move all of the selected files and/" "or folders." msgstr "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." -#: templates/admin/filer/folder/choose_move_destination.html:18 +#: templates/admin/filer/folder/choose_move_destination.html:47 msgid "There are no files and/or folders available to move." -msgstr "" +msgstr "There are no files and/or folders available to move." -#: templates/admin/filer/folder/choose_move_destination.html:20 +#: templates/admin/filer/folder/choose_move_destination.html:52 msgid "" "The following files and/or folders will be moved to a destination folder " "(retaining their tree structure):" msgstr "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" -#: templates/admin/filer/folder/choose_move_destination.html:38 +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 msgid "Move" -msgstr "" +msgstr "Move" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "It is not allowed to move files into same folder" -#: templates/admin/filer/folder/choose_rename_format.html:12 +#: templates/admin/filer/folder/choose_rename_format.html:15 msgid "" "Your account doesn't have permissions to rename all of the selected files." msgstr "" +"Your account doesn't have permissions to rename all of the selected files." -#: templates/admin/filer/folder/choose_rename_format.html:15 +#: templates/admin/filer/folder/choose_rename_format.html:18 msgid "There are no files available to rename." -msgstr "" +msgstr "There are no files available to rename." -#: templates/admin/filer/folder/choose_rename_format.html:17 +#: templates/admin/filer/folder/choose_rename_format.html:20 msgid "" "The following files will be renamed (they will stay in their folders and " "keep original filename, only displayed filename will be changed):" msgstr "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" -#: templates/admin/filer/folder/choose_rename_format.html:54 +#: templates/admin/filer/folder/choose_rename_format.html:59 msgid "Rename" -msgstr "" +msgstr "Rename" -#: templates/admin/filer/folder/directory_listing.html:66 -msgid "Adds a new Folder" -msgstr "" +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "Go back to the parent folder" -#: templates/admin/filer/folder/directory_listing.html:66 -#: templates/image_filer/include/export_dialog.html:34 -msgid "New Folder" -msgstr "" +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "Change current folder details" -#: templates/admin/filer/folder/directory_listing.html:67 -msgid "upload files" -msgstr "" +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "Change" -#: templates/admin/filer/folder/directory_listing.html:67 -msgid "Upload" -msgstr "" +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "Click here to run search for entered phrase" -#: templates/admin/filer/folder/directory_listing.html:74 -msgid "Go back to the parent folder" -msgstr "" +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "Search" -#: templates/admin/filer/folder/directory_listing.html:76 -#: templates/admin/filer/folder/directory_table.html:29 -#: templates/admin/filer/tools/search_form.html:18 -#, python-format -msgid "1 folder" -msgid_plural "%(counter)s folders" -msgstr[0] "" -msgstr[1] "" +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "Close" -#: templates/admin/filer/folder/directory_listing.html:76 -#: templates/admin/filer/folder/directory_table.html:29 -#: templates/admin/filer/tools/search_form.html:19 -#, python-format -msgid "1 file" -msgid_plural "%(counter)s files" -msgstr[0] "" -msgstr[1] "" +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "Limit" -#: templates/admin/filer/folder/directory_listing.html:80 -msgid "Change current folder details" -msgstr "" +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "Check it to limit the search to current folder" -#: templates/admin/filer/folder/directory_listing.html:80 -#: templates/admin/filer/folder/directory_table.html:27 -#: templates/admin/filer/folder/directory_table.html:43 -msgid "Change" -msgstr "" +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "Limit the search to current folder" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "Delete" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "Adds a new Folder" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "New Folder" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "Upload Files" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "You have to select a folder first" -#: templates/admin/filer/folder/directory_table.html:13 +#: templates/admin/filer/folder/directory_table_list.html:16 msgid "Name" -msgstr "" +msgstr "Name" -#: templates/admin/filer/folder/directory_table.html:23 -#: templates/admin/filer/folder/directory_table.html:27 -#: templates/admin/filer/folder/directory_table.html:29 +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "Owner" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "Size" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "Action" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 #, python-format msgid "Change '%(item_label)s' folder details" -msgstr "" +msgstr "Change '%(item_label)s' folder details" -#: templates/admin/filer/folder/directory_table.html:30 -#: templates/admin/filer/folder/directory_table.html:45 -msgid "Owner" -msgstr "" +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "%(counter)s folder" +msgstr[1] "%(counter)s folders" -#: templates/admin/filer/folder/directory_table.html:37 +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "%(counter)s file" +msgstr[1] "%(counter)s files" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "Change folder details" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "Remove folder" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 msgid "Select this file" -msgstr "" +msgstr "Select this file" -#: templates/admin/filer/folder/directory_table.html:39 -#: templates/admin/filer/folder/directory_table.html:43 -#: templates/admin/filer/folder/directory_table.html:44 +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 #, python-format msgid "Change '%(item_label)s' details" -msgstr "" +msgstr "Change '%(item_label)s' details" -#: templates/admin/filer/folder/directory_table.html:42 -#, python-format -msgid "Delete '%(item_label)s'" -msgstr "" - -#: templates/admin/filer/folder/directory_table.html:42 -msgid "Delete" -msgstr "" - -#: templates/admin/filer/folder/directory_table.html:46 +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 msgid "Permissions" -msgstr "" +msgstr "Permissions" -#: templates/admin/filer/folder/directory_table.html:46 +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 msgid "disabled" -msgstr "" +msgstr "disabled" -#: templates/admin/filer/folder/directory_table.html:46 +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 msgid "enabled" -msgstr "" +msgstr "enabled" + +#: templates/admin/filer/folder/directory_table_list.html:144 +#, fuzzy +#| msgid "Move selected files to clipboard" +msgid "URL copied to clipboard" +msgstr "Move selected files to clipboard" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, fuzzy, python-format +#| msgid "Change '%(item_label)s' details" +msgid "Canonical url '%(item_label)s'" +msgstr "Change '%(item_label)s' details" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, fuzzy, python-format +#| msgid "Change '%(item_label)s' details" +msgid "Download '%(item_label)s'" +msgstr "Change '%(item_label)s' details" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "Remove file" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "Drop files here or use the \"Upload Files\" button" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "Drop your file to upload into:" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "Upload" -#: templates/admin/filer/folder/directory_table.html:50 -msgid "Move to clipboard" -msgstr "" +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "cancel" -#: templates/admin/filer/folder/directory_table.html:58 -msgid "there are no files or subfolders" -msgstr "" +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "Upload success!" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "Upload canceled!" -#: templates/admin/filer/folder/directory_table.html:65 +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 msgid "previous" -msgstr "" +msgstr "previous" -#: templates/admin/filer/folder/directory_table.html:69 +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 #, python-format -msgid "" -"\n" -" Page %(number)s of %(num_pages)s.\n" -" " -msgstr "" +msgid "Page %(number)s of %(num_pages)s." +msgstr "Page %(number)s of %(num_pages)s." -#: templates/admin/filer/folder/directory_table.html:75 +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 msgid "next" -msgstr "" +msgstr "next" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "Select all %(total_count)s" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +#, fuzzy +#| msgid "Select this file" +msgid "Select all" +msgstr "Select this file" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +#, fuzzy +#| msgid "Filer" +msgid "Files" +msgstr "Filer" #: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 msgid "Add new" +msgstr "Add new" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" msgstr "" -#: templates/admin/filer/folder/new_folder_form.html:13 +#: templates/admin/filer/folder/new_folder_form.html:15 msgid "Please correct the error below." msgid_plural "Please correct the errors below." -msgstr[0] "" -msgstr[1] "" +msgstr[0] "Please correct the error below." +msgstr[1] "Please correct the errors below." -#: templates/admin/filer/folder/new_folder_form.html:28 +#: templates/admin/filer/folder/new_folder_form.html:30 msgid "Save" -msgstr "" +msgstr "Save" -#: templates/admin/filer/image/change_form.html:21 -msgid "Full size preview" +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." msgstr "" -#: templates/admin/filer/tools/search_form.html:8 -#: templates/admin/filer/tools/search_form.html:14 -msgid "Search" +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." msgstr "" -#: templates/admin/filer/tools/search_form.html:13 -msgid "Enter your search phrase here" -msgstr "" +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "Clipboard" -#: templates/admin/filer/tools/search_form.html:14 -msgid "Click here to" -msgstr "" +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "Paste all items here" -#: templates/admin/filer/tools/search_form.html:14 -msgid "run search for entered phrase" -msgstr "" +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "Move all clipboard files to" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "Empty Clipboard" -#: templates/admin/filer/tools/search_form.html:15 -msgid "Check it to" +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "the clipboard is empty" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "upload failed" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" msgstr "" -#: templates/admin/filer/tools/search_form.html:15 -#: templates/admin/filer/tools/search_form.html:16 -msgid "limit the search to current folder" +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" msgstr "" -#: templates/admin/filer/tools/search_form.html:18 +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +#, fuzzy +#| msgid "file missing" +msgid "File is missing" +msgstr "file missing" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "Type" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "File-size" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "Modified" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "Created" + +#: templates/admin/filer/tools/search_form.html:5 msgid "found" -msgstr "" +msgstr "found" -#: templates/admin/filer/tools/search_form.html:18 +#: templates/admin/filer/tools/search_form.html:5 msgid "and" -msgstr "" +msgstr "and" -#: templates/admin/filer/tools/search_form.html:19 +#: templates/admin/filer/tools/search_form.html:7 msgid "cancel search" -msgstr "" +msgstr "cancel search" -#: templates/admin/filer/tools/upload_button_js.html:24 -#: templates/admin/filer/widgets/admin_file.html:7 -#: templates/admin/filer/widgets/admin_file.html:8 -msgid "file missing" -msgstr "" +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "Clear" -#: templates/admin/filer/tools/clipboard/clipboard.html:7 -msgid "Clipboard" -msgstr "" +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "or drop your file here" -#: templates/admin/filer/tools/clipboard/clipboard.html:19 -msgid "Paste all items here" -msgstr "" +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "no file selected" -#: templates/admin/filer/tools/clipboard/clipboard.html:26 -msgid "discard" -msgstr "" +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "Lookup" -#: templates/admin/filer/tools/clipboard/clipboard.html:26 -msgid "Move all clipboard files to" -msgstr "" +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "Choose File" -#: templates/admin/filer/tools/clipboard/clipboard.html:43 -msgid "the clipboard is empty" -msgstr "" +#: templates/admin/filer/widgets/admin_folder.html:16 +#, fuzzy +#| msgid "Choose File" +msgid "Choose Folder" +msgstr "Choose File" -#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:11 -msgid "upload failed" +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" msgstr "" -#: templates/admin/filer/widgets/admin_file.html:11 -msgid "no file selected" +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" msgstr "" -#: templates/admin/filer/widgets/admin_file.html:14 -#: templates/admin/filer/widgets/admin_file.html:15 -#: templates/admin/filer/widgets/admin_folder.html:7 -#: templates/admin/filer/widgets/admin_folder.html:8 -msgid "Lookup" +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" msgstr "" -#: templates/admin/filer/widgets/admin_file.html:17 -#: templates/admin/filer/widgets/admin_folder.html:10 -msgid "Clear" +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" msgstr "" -#: templates/admin/filer/widgets/admin_folder.html:5 -msgid "none selected" +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" msgstr "" -#: templates/image_filer/folder.html:3 -#, python-format -msgid "Folder '%(folder_label)s' files" -msgstr "" +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." -#: templates/image_filer/folder.html:6 -msgid "File name" -msgstr "" +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" -#: templates/image_filer/image_export_form.html:17 -msgid "export" -msgstr "" +#~ msgid "Open file" +#~ msgstr "Open file" -#: templates/image_filer/image_export_form.html:27 -msgid "download image" -msgstr "" +#~ msgid "Full size preview" +#~ msgstr "Full size preview" -#: templates/image_filer/include/export_dialog.html:13 -msgid "Folder name already taken." -msgstr "" +#~ msgid "Add Description" +#~ msgstr "Add Description" -#: templates/image_filer/include/export_dialog.html:15 -msgid "Submit" -msgstr "" +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#, fuzzy +#~| msgid "Subject location" +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/es/LC_MESSAGES/django.mo b/filer/locale/es/LC_MESSAGES/django.mo new file mode 100644 index 000000000..f11285aee Binary files /dev/null and b/filer/locale/es/LC_MESSAGES/django.mo differ diff --git a/filer/locale/es/LC_MESSAGES/django.po b/filer/locale/es/LC_MESSAGES/django.po new file mode 100644 index 000000000..cc42ddf61 --- /dev/null +++ b/filer/locale/es/LC_MESSAGES/django.po @@ -0,0 +1,1296 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +# Biel Frontera, 2023 +# Cristian Acevedo , 2016 +# David , 2015 +# Jason Gass Martinez , 2016 +# Luis Zárate , 2019 +# Manuel E. Gutierrez , 2013,2015 +# Manuel E. Gutierrez , 2013 +# Pablo, 2015 +# Pablo, 2015 +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Biel Frontera, 2023\n" +"Language-Team: Spanish (http://app.transifex.com/divio/django-filer/language/" +"es/)\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? " +"1 : 2;\n" + +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "No tienes autorización para subir ficheros. " + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" +"No se ha encontrado la carpeta donde guardar el fichero. Por favor, refresca " +"la página y vuelve a probar." + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" +"No se puede utilizar esta carpeta: permiso denegado. Por favor, selecciona " +"otra carpeta." + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "Avanzado" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "URL canónica" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" +"Los elementos deben estar seleccionados para efectuar acciones sobre ellos. " +"Ningún elemento ha sido modificado." + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] " %(total_count)s seleccionado" +msgstr[1] "Todos los %(total_count)s seleccionados" +msgstr[2] "Todos los %(total_count)s seleccionados" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "Listado de directorio para %(folder_name)s" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "0 de %(cnt)s seleccionados" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "Ninguna acción seleccionada." + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "%(count)d archivos movidos con éxito al clipboard." + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "Mover archivos selecionados al clipboard." + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "Permisos para %(count)d ficheros deshabilitados con éxito." + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "Permisos para %(count)d ficheros habilitados con éxito." + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "Habilitar permisos para los archivos seleccionados." + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "Deshabilitar permisos para los archivos seleccionados." + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "Eliminados %(count)d ficheros y/o directorios con éxito." + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "No es posible eliminar ficheros y/o directorios" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "¿Estás seguro?" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "Eliminar ficheros y/o directorios" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "Eliminar ficheros y/o directorios seleccionados" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "Las carpetas con los nombres %s ya existen en el destino seleccionado" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" +"Movidos con éxito %(count)d ficheros y/o directorios al directorio " +"'%(destination)s'." + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "Mover ficheros y/o directorios" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "Mover ficheros y/o directorios seleccionados" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "Cambiado el nombre de %(count)d archivos con éxito." + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "Cambiar el nombre de los archivos" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" +"Copiados con éxito %(count)d ficheros y/o directorios al directorio " +"'%(destination)s'." + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "Copiar ficheros y/o directorios" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "Copiar ficheros y/o directorios seleccionados" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "Cambiado correctamente el tamaño de %(count)d imágenes." + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "Cambiar el tamaño de imágenes." + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "Cambiar el tamaño de imágenes seleccionadas." + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "" +"Sufijo que se añadirá al nombre de los archivos de los archivos copiados." + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "" +"El sufijo debe ser una parte válida de un nombre de fichero, simple y en " +"minúsculas, como \"%(valid)s\"." + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "" +"Formato de cambio de nombre con valor de clave \"%(key)s\" desconocido." + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "Formato de cambio de nombre no válido: %(error)s." + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "opción de miniatura" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "ancho" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "alto" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "recortar" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "ampliar" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "" +"Se debe elegir una opción de miniatura o unos parámetros para el cambio de " +"tamaño." + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "Localización del sujeto." + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "Ubicación del tema principal en la escena. Formato \"x,y\"" + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "Formato de la ubicación del tema inválido" + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "La ubicación del tema está fuera de la imagen" + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "Tu entrada: \"{subject_location}\"." + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "Quién" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "Qué" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "Ya existe un directorio con este nombre." + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "Filer" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "Biblioteca multimedia" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "texto alternativo por defecto" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "leyenda por defecto" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "localización del sujeto" + +#: models/abstract.py:91 +msgid "image" +msgstr "imagen" + +#: models/abstract.py:92 +msgid "images" +msgstr "imágenes" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "usuario" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "archivos" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "portapapeles" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "portapapeles" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "archivo" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "elemento del portapapeles" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "elementos del portapapeles" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "carpeta" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "tamaño del archivo" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "sha1" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "tiene todos los datos obligatorios" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "nombre del archivo original" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "nombre" + +#: models/filemodels.py:116 +msgid "description" +msgstr "descripción" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "propietario" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "subido a" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "modificado el" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "Permisos desactivados" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" +"Desactiva cualquier comprobación de permiso para este archivo. El archivo " +"será accesible públicamente para todos." + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "Padre" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "creado el" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "Carpeta" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "Carpetas" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "todos los elementos" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "sólo este elemento" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "este elemento y todos los hijos" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "hereda" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "permitir" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "denegar" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "tipo" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "grupo" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "todos" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "puede leer" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "puede editar" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "puede añadir hijos" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "permiso de la carpeta" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "permisos de la carpeta" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" +"La carpeta no se puede seleccionar con el tipo \"todos los elementos\"." + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" +"La carpeta se tiene que seleccionar cuando el tipo no es \"todos los " +"elementos\"." + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "Usuario y grupo no se pueden seleccionar a la vez con \"todos\"." + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "Al menos se debe seleccionar un usuario, un grupo o \"todos\"." + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "Todas las carpetas" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "Path lógico" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "Usuario: {user}" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "Grupo: {group}" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "Todos" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "Editar" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "Leer" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "Añadir hijos" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "fecha" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "autor" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "siempre debes dar crédito al autor" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "siempre debes publicar los derechos de autor" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "Ancho en pixel." + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "Alto en pixel." + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "Opciones de miniatura" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "Subidas desordenadas" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "archivos con metadatos perdidos" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "raíz" + +#: settings.py:273 +msgid "Show table view" +msgstr "Muestra la vista de tabla" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "Muestra la vista de miniaturas" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "Ejecutar la acción seleccionada" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "Continuar" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "" +"Haz clic aquí para seleccionar los objetos a través de todas las páginas" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "Seleccionar los %(total_count)s archivos y/o carpetas" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "Limpiar la selección" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "Volver a la página de inicio de admin" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "Inicio" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "Volver a la app Filer" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "Volver a la carpeta raíz" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "Volver a la carpeta '%(folder_name)s'" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "Duplicados" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" +"Borrar los archivos y/o carpetas seleccionados borraría los objetos " +"seleccionados, pero tu cuenta no tiene permiso para borrar los siguientes " +"tipos de objetos:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "" +"Borrar los archivos y/o carpetas requeriría borrar los siguientes objetos " +"relacionados protegidos:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "" +"¿Estás seguro de que quieres borrar los archivos y/o carpetas seleccionados? " +"Los siguientes objetos y sus elementos relacionados serán borrados:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "No, ir atrás" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "Sí, estoy seguro" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "Histórico" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "Ver en la página" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "Volver a" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "página de inicio de la administración" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "Icono de la Carpeta" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." +msgstr "" +"Tu cuenta no tiene permisos para copiar todos los archivos y/o carpetas " +"seleccionados." + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "Volver atrás" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "No hay carpetas de destino disponibles." + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "No hay archivos y/o carpetas disponibles para copiar." + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "" +"Los siguientes archivos y/o carpetas serán copiados a una carpeta de destino " +"(manteniendo su estructura en árbol):" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "Carpeta de destino:" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "Copiar" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "No está permitido copiar los archivos dentro de la misma carpeta" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "" +"Tu cuenta no tiene permisos para cambiar el tamaño de todas las imágenes " +"seleccionadas." + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "No hay imágenes disponibles a las que cambiarles el tamaño." + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "Se les cambiará el tamaño a las siguientes imágenes:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "" +"Elige una opción de miniatura existente o introduce parámetros para el " +"cambio de tamaño:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "" +"Aviso: se cambiará el tamaño de las imágenes en el mismo sitio y los " +"originales se perderán. Considera realizar una copia de aquellas para " +"conservar los originales." + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "Cambiar de tamaño" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." +msgstr "" +"Tu cuenta no tiene permisos para mover todos los archivos y/o carpetas " +"seleccionados." + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "No hay archivos y/o carpetas disponibles para mover." + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "" +"Los siguientes archivos y/o directorios serán movidos a una carpeta de " +"destino (manteniendo su estructura de árbol):" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "Mover" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "No está permitido mover los archivos dentro de la misma carpeta" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "" +"Tu cuenta no tiene permisos para renombrar todos los objetos seleccionados." + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "No hay archivos disponibles a los que cambiar el nombre." + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "" +"Los siguientes archivos serán renombrados (se quedarán en sus carpetas y " +"mantendrán su nombre original, solo los nombres mostrados serán cambiados):" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "Cambiar el nombre" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "Volver a la carpeta padre" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "Cambiar los detalles de la carpeta actual" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "Cambiar" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "Haz clic para correr la búsqueda del texto ingresado" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "Buscar" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "Cerrar" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "Limite" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "Comprueba el límite de búsqueda en la carpeta actual" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "Limitar busqueda a la carpeta actual" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "Borrar" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "Añade una nueva Carpeta" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "Carpeta Nueva" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "Subir archivos." + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "Tiene que seleccionar primero una carpeta" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "Nombre" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "Propietario" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "Tamaño" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "Acción" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "Cambiar los detalles de la carpeta '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "%(counter)s carpeta" +msgstr[1] "%(counter)s carpetas" +msgstr[2] "%(counter)s carpetas" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "%(counter)s archivo" +msgstr[1] "%(counter)s archivos" +msgstr[2] "%(counter)s archivos" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "Cambiar los detalles de la carpeta" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "Eliminar carpeta" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "Seleccionar este archivo" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "Cambiar los detalles de '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "Permisos" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "desactivado" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "activado" + +#: templates/admin/filer/folder/directory_table_list.html:144 +#, fuzzy +#| msgid "Move selected files to clipboard" +msgid "URL copied to clipboard" +msgstr "Mover archivos selecionados al clipboard." + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "Url canónica '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "Descargar '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "Eliminar archivo" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "Suelta los archivos aquí o usa el botón \"Subir archivos\"" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "Suelta el archivo a subir dentro:" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "Subir" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "cancelar" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "Subida exitosa!" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "Subida cancelada!" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "anterior" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "Página %(number)s de %(num_pages)s." + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "siguiente" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "Seleccionar todo %(total_count)s" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "Selecciona todas" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "Ficheros" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "Añadir nuevo" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "Sitio administrativo de Django" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "Por favor, corrige el error indicado abajo." +msgstr[1] "Por favor, corrige los errores indicados abajo." +msgstr[2] "Por favor, corrige los errores indicados abajo." + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "Guardar" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "El navegador no soporta audio." + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "El navegador no soporta vídeo." + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "Portapapeles" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "Pegar aquí todos los elementos" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "Mover todos los archivos del portapapeles a" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "Portapapeles vacío" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "el portapapeles está vacío" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "fallo en la subida" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "Descarga" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "Expande" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "Fichero no encontrado" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "Tipo" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "Tamaño del archivo" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "Modificado" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "Creado" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "encontrado" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "y" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "cancelar la búsqueda" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "Limpiar" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "o suelta aquí tu archivo" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "ningún archivo seleccionado" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "Buscar" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "Selecciona el archivo" + +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "Escoge una carpeta" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" +"Fichero \"{file_name}\": carga denegada por políticas de seguridad del sitio " +"web" + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" +"Fichero \"{file_name}\": carga del tipo {file_type} denegada por políticas " +"de seguridad del sitio web" + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" +"Fichero \"{file_name}\": carga de HTML denegada por políticas de seguridad " +"del sitio web" + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" +"Fichero \"{file_name}\": rechazado por posible vulnerabilidad XSS (Cross-" +"site scripting)" + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" +#~ msgstr[2] "15c0f2d28d6dab1af1f6d94906beb627_pl_2" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/et/LC_MESSAGES/django.mo b/filer/locale/et/LC_MESSAGES/django.mo index 982b54f44..6f688e0c0 100644 Binary files a/filer/locale/et/LC_MESSAGES/django.mo and b/filer/locale/et/LC_MESSAGES/django.mo differ diff --git a/filer/locale/et/LC_MESSAGES/django.po b/filer/locale/et/LC_MESSAGES/django.po index ba48e6a20..44b47474a 100644 --- a/filer/locale/et/LC_MESSAGES/django.po +++ b/filer/locale/et/LC_MESSAGES/django.po @@ -3,483 +3,623 @@ # This file is distributed under the same license as the PACKAGE package. # # Translators: +# Translators: +# Translators: +# Johan Viirok, 2022 +# Martin , 2016 +# Rivo Zängov , 2013 msgid "" msgstr "" -"Project-Id-Version: django-filer\n" +"Project-Id-Version: django Filer\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-07-13 19:10+0200\n" -"PO-Revision-Date: 2012-09-03 20:11+0100\n" -"Last-Translator: Stefan Foulis \n" -"Language-Team: Estonian (http://www.transifex.com/projects/p/django-filer/" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Johan Viirok, 2022\n" +"Language-Team: Estonian (http://app.transifex.com/divio/django-filer/" "language/et/)\n" +"Language: et\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Language: et\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: views.py:103 -msgid "Folder with this name already exists." +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." msgstr "" -#: admin/fileadmin.py:41 +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 msgid "Advanced" msgstr "" -#: admin/folderadmin.py:324 admin/folderadmin.py:427 +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 msgid "" "Items must be selected in order to perform actions on them. No items have " "been changed." msgstr "" -#: admin/folderadmin.py:344 +#: admin/folderadmin.py:434 #, python-format msgid "%(total_count)s selected" msgid_plural "All %(total_count)s selected" msgstr[0] "" msgstr[1] "" -#: admin/folderadmin.py:377 +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "" + +#: admin/folderadmin.py:475 #, python-format msgid "0 of %(cnt)s selected" msgstr "" -#: admin/folderadmin.py:456 +#: admin/folderadmin.py:612 msgid "No action selected." -msgstr "" +msgstr "Ühtegi tegevust pole valitud." -#: admin/folderadmin.py:497 +#: admin/folderadmin.py:664 #, python-format msgid "Successfully moved %(count)d files to clipboard." msgstr "" -#: admin/folderadmin.py:503 +#: admin/folderadmin.py:669 msgid "Move selected files to clipboard" msgstr "" -#: admin/folderadmin.py:537 +#: admin/folderadmin.py:709 #, python-format msgid "Successfully disabled permissions for %(count)d files." msgstr "" -#: admin/folderadmin.py:541 +#: admin/folderadmin.py:711 #, python-format msgid "Successfully enabled permissions for %(count)d files." msgstr "" -#: admin/folderadmin.py:550 +#: admin/folderadmin.py:719 msgid "Enable permissions for selected files" msgstr "" -#: admin/folderadmin.py:555 +#: admin/folderadmin.py:725 msgid "Disable permissions for selected files" msgstr "" -#: admin/folderadmin.py:623 +#: admin/folderadmin.py:789 #, python-format msgid "Successfully deleted %(count)d files and/or folders." msgstr "" -#: admin/folderadmin.py:630 +#: admin/folderadmin.py:794 msgid "Cannot delete files and/or folders" msgstr "" -#: admin/folderadmin.py:632 +#: admin/folderadmin.py:796 msgid "Are you sure?" -msgstr "" +msgstr "Oled sa kindel?" -#: admin/folderadmin.py:637 +#: admin/folderadmin.py:802 msgid "Delete files and/or folders" -msgstr "" +msgstr "Kustuta failid ja/või kaustad" -#: admin/folderadmin.py:656 +#: admin/folderadmin.py:823 msgid "Delete selected files and/or folders" +msgstr "Kustuta valitud failid ja/või kaustad" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" msgstr "" -#: admin/folderadmin.py:771 +#: admin/folderadmin.py:934 #, python-format msgid "" "Successfully moved %(count)d files and/or folders to folder " "'%(destination)s'." msgstr "" -#: admin/folderadmin.py:778 admin/folderadmin.py:780 +#: admin/folderadmin.py:942 admin/folderadmin.py:944 msgid "Move files and/or folders" msgstr "" -#: admin/folderadmin.py:797 +#: admin/folderadmin.py:959 msgid "Move selected files and/or folders" msgstr "" -#: admin/folderadmin.py:854 +#: admin/folderadmin.py:1016 #, python-format msgid "Successfully renamed %(count)d files." msgstr "" -#: admin/folderadmin.py:862 admin/folderadmin.py:864 admin/folderadmin.py:881 +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 msgid "Rename files" -msgstr "" +msgstr "Nimeta failid ümber" -#: admin/folderadmin.py:975 +#: admin/folderadmin.py:1137 #, python-format msgid "" "Successfully copied %(count)d files and/or folders to folder " "'%(destination)s'." msgstr "" -#: admin/folderadmin.py:989 admin/folderadmin.py:991 +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 msgid "Copy files and/or folders" msgstr "" -#: admin/folderadmin.py:1010 +#: admin/folderadmin.py:1174 msgid "Copy selected files and/or folders" msgstr "" -#: admin/folderadmin.py:1105 +#: admin/folderadmin.py:1279 #, python-format msgid "Successfully resized %(count)d images." msgstr "" -#: admin/folderadmin.py:1113 admin/folderadmin.py:1115 +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 msgid "Resize images" msgstr "" -#: admin/folderadmin.py:1133 +#: admin/folderadmin.py:1303 msgid "Resize selected images" msgstr "" -#: admin/forms.py:26 +#: admin/forms.py:24 msgid "Suffix which will be appended to filenames of copied files." msgstr "" -#: admin/forms.py:33 +#: admin/forms.py:31 #, python-format msgid "" "Suffix should be a valid, simple and lowercase filename part, like " "\"%(valid)s\"." msgstr "" -#: admin/forms.py:54 +#: admin/forms.py:52 #, python-format msgid "Unknown rename format value key \"%(key)s\"." msgstr "" -#: admin/forms.py:56 +#: admin/forms.py:54 #, python-format msgid "Invalid rename format: %(error)s." msgstr "" -#: admin/forms.py:62 +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 msgid "thumbnail option" -msgstr "" +msgstr "pisipildi valikud" -#: admin/forms.py:63 +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 msgid "width" -msgstr "" +msgstr "laius" -#: admin/forms.py:64 +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 msgid "height" -msgstr "" +msgstr "kõrgus" -#: admin/forms.py:65 +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 msgid "crop" -msgstr "" +msgstr "lõika" -#: admin/forms.py:66 +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 msgid "upscale" -msgstr "" +msgstr "suurenda" -#: admin/forms.py:71 +#: admin/forms.py:79 msgid "Thumbnail option or resize parameters must be choosen." msgstr "" -#: admin/forms.py:73 -msgid "Resize parameters must be choosen." +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" msgstr "" -#: admin/imageadmin.py:12 -msgid "Subject location" +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." msgstr "" -#: admin/imageadmin.py:13 -msgid "Location of the main subject of the scene." +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " msgstr "" -#: models/clipboardmodels.py:9 models/foldermodels.py:236 -msgid "user" +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " msgstr "" -#: models/clipboardmodels.py:11 models/filemodels.py:287 -msgid "files" +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " msgstr "" -#: models/clipboardmodels.py:34 models/clipboardmodels.py:40 -msgid "clipboard" +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" msgstr "" -#: models/clipboardmodels.py:35 -msgid "clipboards" +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" msgstr "" -#: models/clipboardmodels.py:39 models/filemodels.py:35 -#: models/filemodels.py:286 -msgid "file" +#: admin/views.py:55 +msgid "Folder with this name already exists." msgstr "" -#: models/clipboardmodels.py:44 -msgid "clipboard item" +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "Filer" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" msgstr "" -#: models/clipboardmodels.py:45 -msgid "clipboard items" +#: models/abstract.py:62 +msgid "default alt text" +msgstr "" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "" + +#: models/abstract.py:91 +msgid "image" +msgstr "pilt" + +#: models/abstract.py:92 +msgid "images" +msgstr "pildid" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." msgstr "" -#: models/filemodels.py:33 templates/admin/filer/folder/change_form.html:9 -#: templates/admin/filer/folder/directory_listing.html:74 +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "kasutaja" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "failid" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "lõikalaud" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "lõikelauad" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "fail" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "lõikelaua kirje" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "lõikelaua kirjed" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 #: templates/admin/filer/folder/new_folder_form.html:4 -#: templates/admin/filer/tools/clipboard/clipboard.html:26 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 msgid "folder" -msgstr "" +msgstr "kaust" -#: models/filemodels.py:36 +#: models/filemodels.py:81 msgid "file size" -msgstr "" +msgstr "failisuurus" -#: models/filemodels.py:38 +#: models/filemodels.py:87 msgid "sha1" -msgstr "" +msgstr "sha1" -#: models/filemodels.py:40 +#: models/filemodels.py:94 msgid "has all mandatory data" msgstr "" -#: models/filemodels.py:42 +#: models/filemodels.py:100 msgid "original filename" -msgstr "" +msgstr "algne failinimi" -#: models/filemodels.py:44 models/foldermodels.py:99 +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 msgid "name" -msgstr "" +msgstr "nimi" -#: models/filemodels.py:46 +#: models/filemodels.py:116 msgid "description" -msgstr "" +msgstr "kirjeldus" -#: models/filemodels.py:50 +#: models/filemodels.py:125 models/foldermodels.py:108 msgid "owner" -msgstr "" +msgstr "omanik" -#: models/filemodels.py:52 models/foldermodels.py:105 +#: models/filemodels.py:129 models/foldermodels.py:116 msgid "uploaded at" -msgstr "" +msgstr "üles laaditud" -#: models/filemodels.py:53 models/foldermodels.py:108 +#: models/filemodels.py:134 models/foldermodels.py:126 msgid "modified at" -msgstr "" +msgstr "muudetud" -#: models/filemodels.py:57 +#: models/filemodels.py:140 msgid "Permissions disabled" msgstr "" -#: models/filemodels.py:58 -msgid "Disable any permission checking for this " +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" + +#: models/foldermodels.py:94 +msgid "parent" msgstr "" -#: models/foldermodels.py:107 +#: models/foldermodels.py:121 msgid "created at" -msgstr "" +msgstr "loodud" -#: models/foldermodels.py:211 -#: templates/admin/filer/widgets/admin_folder.html:3 -#: templates/admin/filer/widgets/admin_folder.html:5 +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 msgid "Folder" -msgstr "" +msgstr "Kaust" -#: models/foldermodels.py:212 +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 msgid "Folders" -msgstr "" +msgstr "Kaustad" -#: models/foldermodels.py:227 +#: models/foldermodels.py:260 msgid "all items" -msgstr "" +msgstr "kõik kirjed" -#: models/foldermodels.py:228 +#: models/foldermodels.py:261 msgid "this item only" -msgstr "" +msgstr "ainult see kirje" -#: models/foldermodels.py:229 +#: models/foldermodels.py:262 msgid "this item and all children" +msgstr "see kirje ja kõik alamkirjed" + +#: models/foldermodels.py:266 +msgid "inherit" msgstr "" -#: models/foldermodels.py:233 +#: models/foldermodels.py:267 +msgid "allow" +msgstr "luba" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "keeldu" + +#: models/foldermodels.py:280 msgid "type" -msgstr "" +msgstr "tüüp" -#: models/foldermodels.py:239 +#: models/foldermodels.py:297 msgid "group" -msgstr "" +msgstr "grupp" -#: models/foldermodels.py:240 +#: models/foldermodels.py:304 msgid "everybody" -msgstr "" +msgstr "kõik" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "saab lugeda" -#: models/foldermodels.py:242 +#: models/foldermodels.py:317 msgid "can edit" +msgstr "saab mutua" + +#: models/foldermodels.py:325 +msgid "can add children" msgstr "" -#: models/foldermodels.py:243 -msgid "can read" +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "kausta õigus" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "kausta õigused" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." msgstr "" -#: models/foldermodels.py:244 -msgid "can add children" +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." msgstr "" -#: models/foldermodels.py:273 -msgid "folder permission" +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." msgstr "" -#: models/foldermodels.py:274 -msgid "folder permissions" +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." msgstr "" -#: models/imagemodels.py:39 -msgid "date taken" +#: models/foldermodels.py:360 +msgid "All Folders" msgstr "" -#: models/imagemodels.py:42 -msgid "default alt text" +#: models/foldermodels.py:362 +msgid "Logical Path" msgstr "" -#: models/imagemodels.py:43 -msgid "default caption" +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" msgstr "" -#: models/imagemodels.py:45 templates/image_filer/image.html:6 -msgid "author" +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" msgstr "" -#: models/imagemodels.py:47 -msgid "must always publish author credit" +#: models/foldermodels.py:375 +msgid "Everybody" msgstr "" -#: models/imagemodels.py:48 -msgid "must always publish copyright" +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" msgstr "" -#: models/imagemodels.py:50 -msgid "subject location" +#: models/foldermodels.py:389 +msgid "Read" msgstr "" -#: models/imagemodels.py:200 -msgid "image" +#: models/foldermodels.py:390 +msgid "Add children" msgstr "" -#: models/imagemodels.py:201 -msgid "images" +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "autor" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" msgstr "" -#: models/virtualitems.py:45 -#: templates/admin/filer/tools/clipboard/clipboard.html:26 -msgid "unfiled files" +#: models/imagemodels.py:37 +msgid "must always publish copyright" msgstr "" -#: models/virtualitems.py:59 +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "laius pikslites" + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "kõrgus pikslites" + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "" + +#: models/virtualitems.py:73 msgid "files with missing metadata" msgstr "" -#: models/virtualitems.py:73 templates/admin/filer/breadcrumbs.html:6 -#: templates/admin/filer/folder/change_form.html:9 -#: templates/admin/filer/folder/directory_listing.html:74 -#: templates/image_filer/image_export_form.html:10 +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 msgid "root" msgstr "" -#: templates/admin/filer/actions.html:4 +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 msgid "Run the selected action" msgstr "" -#: templates/admin/filer/actions.html:4 +#: templates/admin/filer/actions.html:5 msgid "Go" -msgstr "" +msgstr "Mine" -#: templates/admin/filer/actions.html:11 +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 msgid "Click here to select the objects across all pages" msgstr "" -#: templates/admin/filer/actions.html:11 +#: templates/admin/filer/actions.html:14 #, python-format msgid "Select all %(total_count)s files and/or folders" msgstr "" -#: templates/admin/filer/actions.html:13 +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 msgid "Clear selection" -msgstr "" +msgstr "Tühista valik" #: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 msgid "Go back to admin homepage" msgstr "" #: templates/admin/filer/breadcrumbs.html:4 -#: templates/admin/filer/folder/change_form.html:7 -#: templates/image_filer/image_export_form.html:7 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 msgid "Home" -msgstr "" +msgstr "Koduleht" #: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 msgid "Go back to Filer app" msgstr "" -#: templates/admin/filer/breadcrumbs.html:5 -#: templates/admin/filer/folder/change_form.html:8 -#: templates/image_filer/image_export_form.html:8 -msgid "Filer" -msgstr "" - #: templates/admin/filer/breadcrumbs.html:6 -#: templates/image_filer/image_export_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:35 msgid "Go back to root folder" -msgstr "" +msgstr "Tagasi peakausta" #: templates/admin/filer/breadcrumbs.html:8 -#: templates/admin/filer/breadcrumbs.html:11 -#: templates/admin/filer/folder/change_form.html:11 -#: templates/image_filer/image_export_form.html:12 -#: templates/image_filer/image_export_form.html:14 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 #, python-format msgid "Go back to '%(folder_name)s' folder" msgstr "" -#: templates/admin/filer/change_form.html:28 -msgid "duplicates" -msgstr "" - -#: templates/admin/filer/delete_confirmation.html:13 -#, python-format -msgid "" -"Deleting the %(object_name)s '%(escaped_object)s' would result in deleting " -"related objects, but your account doesn't have permission to delete the " -"following types of objects:" -msgstr "" - -#: templates/admin/filer/delete_confirmation.html:21 -#, python-format -msgid "" -"Deleting the %(object_name)s '%(escaped_object)s' would require deleting the " -"following protected related objects:" -msgstr "" - -#: templates/admin/filer/delete_confirmation.html:29 -#, python-format -msgid "" -"Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? " -"All of the following related items will be deleted:" -msgstr "" - -#: templates/admin/filer/delete_confirmation.html:34 -#: templates/admin/filer/delete_selected_files_confirmation.html:45 -msgid "Yes, I'm sure" -msgstr "" +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "Duplikaadid" #: templates/admin/filer/delete_selected_files_confirmation.html:11 msgid "" @@ -500,386 +640,588 @@ msgid "" "the following objects and their related items will be deleted:" msgstr "" -#: templates/admin/filer/folder/change_form.html:7 -#: templates/admin/filer/folder/change_form.html:8 -#: templates/admin/filer/folder/change_form.html:9 -#: templates/admin/filer/folder/directory_listing.html:74 -#: templates/image_filer/image_export_form.html:7 -#: templates/image_filer/image_export_form.html:8 -#: templates/image_filer/image_export_form.html:16 -msgid "Go back to" -msgstr "" +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "Ei, vii mind tagasi" -#: templates/admin/filer/folder/change_form.html:7 -#: templates/image_filer/image_export_form.html:7 -msgid "admin homepage" -msgstr "" +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "Jah, olen kindel" -#: templates/admin/filer/folder/change_form.html:22 -#: templates/admin/filer/image/change_form.html:9 +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 msgid "History" -msgstr "" +msgstr "Ajalugu" +#: templates/admin/filer/file/change_form.html:37 #: templates/admin/filer/folder/change_form.html:23 -#: templates/admin/filer/image/change_form.html:10 +#: templates/admin/filer/image/change_form.html:37 msgid "View on site" -msgstr "" +msgstr "Vaata saidil" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "Mine tagasi" -#: templates/admin/filer/folder/change_form.html:35 -#: templates/admin/filer/folder/directory_listing.html:75 -#: templates/admin/filer/folder/directory_listing.html:85 -#: templates/admin/filer/folder/directory_table.html:23 +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "admini koduleht" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 msgid "Folder Icon" -msgstr "" +msgstr "Kausta ikoon" -#: templates/admin/filer/folder/choose_copy_destination.html:12 +#: templates/admin/filer/folder/choose_copy_destination.html:23 msgid "" "Your account doesn't have permissions to copy all of the selected files and/" "or folders." msgstr "" -#: templates/admin/filer/folder/choose_copy_destination.html:15 -#: templates/admin/filer/folder/choose_move_destination.html:15 +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 msgid "There are no destination folders available." msgstr "" -#: templates/admin/filer/folder/choose_copy_destination.html:18 +#: templates/admin/filer/folder/choose_copy_destination.html:35 msgid "There are no files and/or folders available to copy." msgstr "" -#: templates/admin/filer/folder/choose_copy_destination.html:20 +#: templates/admin/filer/folder/choose_copy_destination.html:40 msgid "" "The following files and/or folders will be copied to a destination folder " "(retaining their tree structure):" msgstr "" -#: templates/admin/filer/folder/choose_copy_destination.html:32 -#: templates/admin/filer/folder/choose_move_destination.html:32 +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 msgid "Destination folder:" msgstr "" -#: templates/admin/filer/folder/choose_copy_destination.html:39 +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 msgid "Copy" +msgstr "Kopeeri" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" msgstr "" -#: templates/admin/filer/folder/choose_images_resize_options.html:12 +#: templates/admin/filer/folder/choose_images_resize_options.html:15 msgid "" "Your account doesn't have permissions to resize all of the selected images." msgstr "" -#: templates/admin/filer/folder/choose_images_resize_options.html:15 +#: templates/admin/filer/folder/choose_images_resize_options.html:18 msgid "There are no images available to resize." msgstr "" -#: templates/admin/filer/folder/choose_images_resize_options.html:17 +#: templates/admin/filer/folder/choose_images_resize_options.html:20 msgid "The following images will be resized:" msgstr "" -#: templates/admin/filer/folder/choose_images_resize_options.html:30 -msgid "Choose an existing thumbnail option or enter resize parameters:" -msgstr "" - #: templates/admin/filer/folder/choose_images_resize_options.html:32 -msgid "Choose resize parameters:" +msgid "Choose an existing thumbnail option or enter resize parameters:" msgstr "" -#: templates/admin/filer/folder/choose_images_resize_options.html:35 +#: templates/admin/filer/folder/choose_images_resize_options.html:36 msgid "" "Warning: Images will be resized in-place and originals will be lost. Maybe " "first make a copy of them to retain the originals." msgstr "" -#: templates/admin/filer/folder/choose_images_resize_options.html:36 +#: templates/admin/filer/folder/choose_images_resize_options.html:39 msgid "Resize" -msgstr "" +msgstr "Muuda suurust" -#: templates/admin/filer/folder/choose_move_destination.html:12 +#: templates/admin/filer/folder/choose_move_destination.html:35 msgid "" "Your account doesn't have permissions to move all of the selected files and/" "or folders." msgstr "" -#: templates/admin/filer/folder/choose_move_destination.html:18 +#: templates/admin/filer/folder/choose_move_destination.html:47 msgid "There are no files and/or folders available to move." msgstr "" -#: templates/admin/filer/folder/choose_move_destination.html:20 +#: templates/admin/filer/folder/choose_move_destination.html:52 msgid "" "The following files and/or folders will be moved to a destination folder " "(retaining their tree structure):" msgstr "" -#: templates/admin/filer/folder/choose_move_destination.html:38 +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 msgid "Move" +msgstr "Liiguta" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" msgstr "" -#: templates/admin/filer/folder/choose_rename_format.html:12 +#: templates/admin/filer/folder/choose_rename_format.html:15 msgid "" "Your account doesn't have permissions to rename all of the selected files." msgstr "" -#: templates/admin/filer/folder/choose_rename_format.html:15 +#: templates/admin/filer/folder/choose_rename_format.html:18 msgid "There are no files available to rename." msgstr "" -#: templates/admin/filer/folder/choose_rename_format.html:17 +#: templates/admin/filer/folder/choose_rename_format.html:20 msgid "" "The following files will be renamed (they will stay in their folders and " "keep original filename, only displayed filename will be changed):" msgstr "" -#: templates/admin/filer/folder/choose_rename_format.html:54 +#: templates/admin/filer/folder/choose_rename_format.html:59 msgid "Rename" -msgstr "" +msgstr "Nimeta ümber" -#: templates/admin/filer/folder/directory_listing.html:66 -msgid "Adds a new Folder" +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "Mine tagasi peamisesse kausta" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" msgstr "" -#: templates/admin/filer/folder/directory_listing.html:66 -#: templates/image_filer/include/export_dialog.html:34 -msgid "New Folder" +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "Muuda" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" msgstr "" -#: templates/admin/filer/folder/directory_listing.html:67 -msgid "upload files" +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "Otsi" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "Sulge" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" msgstr "" -#: templates/admin/filer/folder/directory_listing.html:67 -msgid "Upload" +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" msgstr "" -#: templates/admin/filer/folder/directory_listing.html:74 -msgid "Go back to the parent folder" +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" msgstr "" -#: templates/admin/filer/folder/directory_listing.html:76 -#: templates/admin/filer/folder/directory_table.html:29 -#: templates/admin/filer/tools/search_form.html:18 -#, python-format -msgid "1 folder" -msgid_plural "%(counter)s folders" -msgstr[0] "" -msgstr[1] "" +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "Kustuta" -#: templates/admin/filer/folder/directory_listing.html:76 -#: templates/admin/filer/folder/directory_table.html:29 -#: templates/admin/filer/tools/search_form.html:19 -#, python-format -msgid "1 file" -msgid_plural "%(counter)s files" -msgstr[0] "" -msgstr[1] "" +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "Lisab uue kausta" -#: templates/admin/filer/folder/directory_listing.html:80 -msgid "Change current folder details" +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "Uus kaust" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" msgstr "" -#: templates/admin/filer/folder/directory_listing.html:80 -#: templates/admin/filer/folder/directory_table.html:27 -#: templates/admin/filer/folder/directory_table.html:43 -msgid "Change" +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" msgstr "" -#: templates/admin/filer/folder/directory_table.html:13 +#: templates/admin/filer/folder/directory_table_list.html:16 msgid "Name" +msgstr "Nimi" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "Omanik" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "Suurus" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" msgstr "" -#: templates/admin/filer/folder/directory_table.html:23 -#: templates/admin/filer/folder/directory_table.html:27 -#: templates/admin/filer/folder/directory_table.html:29 +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 #, python-format msgid "Change '%(item_label)s' folder details" msgstr "" -#: templates/admin/filer/folder/directory_table.html:30 -#: templates/admin/filer/folder/directory_table.html:45 -msgid "Owner" +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "%(counter)s kaust" +msgstr[1] "%(counter)s kausta" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "%(counter)s fail" +msgstr[1] "%(counter)s faili" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" msgstr "" -#: templates/admin/filer/folder/directory_table.html:37 +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "Eemalda kaust" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 msgid "Select this file" -msgstr "" +msgstr "Vali see fail" -#: templates/admin/filer/folder/directory_table.html:39 -#: templates/admin/filer/folder/directory_table.html:43 -#: templates/admin/filer/folder/directory_table.html:44 +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 #, python-format msgid "Change '%(item_label)s' details" msgstr "" -#: templates/admin/filer/folder/directory_table.html:42 -#, python-format -msgid "Delete '%(item_label)s'" -msgstr "" - -#: templates/admin/filer/folder/directory_table.html:42 -msgid "Delete" -msgstr "" - -#: templates/admin/filer/folder/directory_table.html:46 +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 msgid "Permissions" -msgstr "" +msgstr "Õigused" -#: templates/admin/filer/folder/directory_table.html:46 +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 msgid "disabled" -msgstr "" +msgstr "välja lülitatud" -#: templates/admin/filer/folder/directory_table.html:46 +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 msgid "enabled" +msgstr "sisse lülitatud" + +#: templates/admin/filer/folder/directory_table_list.html:144 +msgid "URL copied to clipboard" msgstr "" -#: templates/admin/filer/folder/directory_table.html:50 -msgid "Move to clipboard" +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "Lae alla '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "Eemalda fail" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" msgstr "" -#: templates/admin/filer/folder/directory_table.html:58 -msgid "there are no files or subfolders" +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" msgstr "" -#: templates/admin/filer/folder/directory_table.html:65 +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "Laadi üles" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "tühista" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "Üleslaadimine õnnestus!" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "Üleslaadimine tühistatud!" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 msgid "previous" -msgstr "" +msgstr "eelmine" -#: templates/admin/filer/folder/directory_table.html:69 +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 #, python-format -msgid "" -"\n" -" Page %(number)s of %(num_pages)s.\n" -" " -msgstr "" +msgid "Page %(number)s of %(num_pages)s." +msgstr "Lehekülg %(number)s / %(num_pages)s." -#: templates/admin/filer/folder/directory_table.html:75 +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 msgid "next" +msgstr "järgmine" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "Vali kõik %(total_count)s" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" msgstr "" #: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 msgid "Add new" +msgstr "Lisa uus" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" msgstr "" -#: templates/admin/filer/folder/new_folder_form.html:13 +#: templates/admin/filer/folder/new_folder_form.html:15 msgid "Please correct the error below." msgid_plural "Please correct the errors below." msgstr[0] "" msgstr[1] "" -#: templates/admin/filer/folder/new_folder_form.html:28 +#: templates/admin/filer/folder/new_folder_form.html:30 msgid "Save" -msgstr "" +msgstr "Salvesta" -#: templates/admin/filer/image/change_form.html:21 -msgid "Full size preview" +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." msgstr "" -#: templates/admin/filer/tools/search_form.html:8 -#: templates/admin/filer/tools/search_form.html:14 -msgid "Search" +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." msgstr "" -#: templates/admin/filer/tools/search_form.html:13 -msgid "Enter your search phrase here" +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "Lõikelaud" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" msgstr "" -#: templates/admin/filer/tools/search_form.html:14 -msgid "Click here to" +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" msgstr "" -#: templates/admin/filer/tools/search_form.html:14 -msgid "run search for entered phrase" +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "Tühjenda lõikelaud" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "lõikelaud on tühi" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "üleslaadimine ebaõnnestus" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" msgstr "" -#: templates/admin/filer/tools/search_form.html:15 -msgid "Check it to" +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" msgstr "" -#: templates/admin/filer/tools/search_form.html:15 -#: templates/admin/filer/tools/search_form.html:16 -msgid "limit the search to current folder" +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" msgstr "" -#: templates/admin/filer/tools/search_form.html:18 +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "Tüüp" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "Faili suurus" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "Muudetud" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "Loodud" + +#: templates/admin/filer/tools/search_form.html:5 msgid "found" -msgstr "" +msgstr "leitud" -#: templates/admin/filer/tools/search_form.html:18 +#: templates/admin/filer/tools/search_form.html:5 msgid "and" -msgstr "" +msgstr "ja" -#: templates/admin/filer/tools/search_form.html:19 +#: templates/admin/filer/tools/search_form.html:7 msgid "cancel search" -msgstr "" +msgstr "tühista otsing" -#: templates/admin/filer/tools/upload_button_js.html:24 -#: templates/admin/filer/widgets/admin_file.html:7 -#: templates/admin/filer/widgets/admin_file.html:8 -msgid "file missing" -msgstr "" +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "Tühjenda" -#: templates/admin/filer/tools/clipboard/clipboard.html:7 -msgid "Clipboard" -msgstr "" +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "või lohista fail siia" -#: templates/admin/filer/tools/clipboard/clipboard.html:19 -msgid "Paste all items here" -msgstr "" +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "ühtegi faili pole valitud" -#: templates/admin/filer/tools/clipboard/clipboard.html:26 -msgid "discard" +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" msgstr "" -#: templates/admin/filer/tools/clipboard/clipboard.html:26 -msgid "Move all clipboard files to" -msgstr "" +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "Vali fail" -#: templates/admin/filer/tools/clipboard/clipboard.html:43 -msgid "the clipboard is empty" +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" msgstr "" -#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:11 -msgid "upload failed" +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" msgstr "" -#: templates/admin/filer/widgets/admin_file.html:11 -msgid "no file selected" +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" msgstr "" -#: templates/admin/filer/widgets/admin_file.html:14 -#: templates/admin/filer/widgets/admin_file.html:15 -#: templates/admin/filer/widgets/admin_folder.html:7 -#: templates/admin/filer/widgets/admin_folder.html:8 -msgid "Lookup" +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" msgstr "" -#: templates/admin/filer/widgets/admin_file.html:17 -#: templates/admin/filer/widgets/admin_folder.html:10 -msgid "Clear" +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" msgstr "" -#: templates/admin/filer/widgets/admin_folder.html:5 -msgid "none selected" +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" msgstr "" -#: templates/image_filer/folder.html:3 -#, python-format -msgid "Folder '%(folder_label)s' files" -msgstr "" +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." -#: templates/image_filer/folder.html:6 -msgid "File name" -msgstr "" +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" -#: templates/image_filer/image_export_form.html:17 -msgid "export" -msgstr "" +#~ msgid "Open file" +#~ msgstr "Open file" -#: templates/image_filer/image_export_form.html:27 -msgid "download image" -msgstr "" +#~ msgid "Full size preview" +#~ msgstr "Full size preview" -#: templates/image_filer/include/export_dialog.html:13 -msgid "Folder name already taken." -msgstr "" +#~ msgid "Add Description" +#~ msgstr "Add Description" -#: templates/image_filer/include/export_dialog.html:15 -msgid "Submit" -msgstr "" +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/eu/LC_MESSAGES/django.mo b/filer/locale/eu/LC_MESSAGES/django.mo new file mode 100644 index 000000000..0c1dfafb6 Binary files /dev/null and b/filer/locale/eu/LC_MESSAGES/django.mo differ diff --git a/filer/locale/eu/LC_MESSAGES/django.po b/filer/locale/eu/LC_MESSAGES/django.po new file mode 100644 index 000000000..a28a55d23 --- /dev/null +++ b/filer/locale/eu/LC_MESSAGES/django.po @@ -0,0 +1,1241 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +# Ales Zabala Alava , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Ales Zabala Alava , 2013\n" +"Language-Team: Basque (http://app.transifex.com/divio/django-filer/language/" +"eu/)\n" +"Language: eu\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" + +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "" + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "Aurreratua" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" +"Elementuak hautatu behar dira beraiekin zeozer egiteko. Ez da elementurik " +"aldatu." + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "bat haututa" +msgstr[1] "%(total_count)s hautatuta" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "%(cnt)s-(e)tik 0 hautatuta" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "Ez da ekintzarik hautatu" + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "%(count)d fitxategi arbelera mugituta." + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "Hautatutako fitxategiak arbelara mugitu" + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "%(count)d fitxategientzako baimenak ezgaituta." + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "%(count)d fitxategientzako baimenak gaituta." + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "Hautatutako fitxategientzako baimenak gaitu" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "Hautatutako fitxategientzako baimenak ezgaitu" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "%(count)d fitxategi eta/edo karpeta ezabatuta." + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "Ezin dira fitxategia eta/edo karpetak ezabatu" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "Ziur zaude?" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "Ezabatu fitxategi eta/edo karpetak" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "Ezabatu hautatutako fitxategi eta/edo karpetak" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" +"%(count)d fitxategi eta/edo karpeta '%(destination)s' karpetara mugituta." + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "Fitxategi eta/edo karpetak mugitu" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "Hautatutako fitxategi eta/edo karpetak mugitu" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "%(count)d fitxategi berrizendatuta." + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "Fitxategiak berrizendatu" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" +"%(count)d fitxategi eta/edo karpeta %(destination)s karpetara kopiatuta." + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "Fitxategi eta/edo karpetak kopiatu" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "Hautatutako fitxategi eta/edo karpetak kopiatu" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "%(count)d irudien tamaina aldatuta." + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "Irudien tamaina aldatu" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "Hautatutako irudien tamaina aldatu" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "Kopiatutako fitxategiei gehituko zaien atzizkia." + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "" +"Atzizkia baliozko, sinple eta letra xehetan dagoen fitxategi izen zatia izan " +"beharko luke, \"%(valid)s\" bezala." + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "Berrizendatze formatuko gako balio ezezaguna \"%(key)s\"." + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "Berrizendatze formatu okerra: %(error)s." + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "argazkitxoaren aukerak" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "zabalera" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "altuera" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "moztu" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "handitu" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "" +"Argazkitxo aukerak edo tamaina aldatzeko parametroak zehaztu behar dira." + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "Subjektuaren kokapena" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "" + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "" + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "" + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "" + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "Izen honetako karpeta badago." + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "Filer" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "defektuzko testu alternatiboa" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "defektuzko epigrafea" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "subjektuaren kokapena" + +#: models/abstract.py:91 +msgid "image" +msgstr "irudia" + +#: models/abstract.py:92 +msgid "images" +msgstr "irudiak" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "erabiltzailea" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "fitxategiak" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "arbela" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "arbelak" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "fitxategia" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "arbeleko elementua" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "arbeleko elementuak" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "karpeta" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "fitxategi tamaina" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "sha1" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "beharrezko datu guztiak ditu" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "jatorrizko fitxategi izena" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "izena" + +#: models/filemodels.py:116 +msgid "description" +msgstr "deskribapena" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "jaea" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "noiz igota" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "noiz aldatua" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "Baimenak ezgaituta" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "noiz sortua" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "Karpeta" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "Karpetak" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "elementu guztiak" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "elementu hau bakarrik" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "elementu hau eta bere semeak" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "mota" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "taldea" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "edonor" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "irakurri dezake" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "editatu dezake" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "semeak gehitu ditzake" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "karpeta baimena" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "karpeta baimenak" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "" + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "sortze data" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "egilea" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "egilearen kredituak beti argitaratu behar dira" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "copyright-a beti argitaratu behar da" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "metadatuak faltan dituzten fitxategiak" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "erroa" + +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "Hautatutako ekintza abiarazi" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "Joan" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "Hemen klikatu orri guztietako objektuak hautatzeko" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "Hautatu %(total_count)s fitxategi eta/edo karpeta guztiak" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "Hautapena hustu" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "Kudeaketa hasierara itzuli" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "Etxea" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "Filer aplikaziora itzuli" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "Erro karpetara itzuli" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "'%(folder_name)s karpetara itzuli'" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "" +"Ziur hautatutako fitxategi eta/edo karpetak ezabatu nahi dituzula? Ondoko " +"objektu eta erlazionatutako elementu guztiak ezabatuko lirateke:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "Aurrekoak" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "Webgunean ikusi" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "Itzuli hona:" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "kudeaketa hasiera" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "Karpeta ikonoa" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "Ez dago helburuko karpetarik eskuragarri." + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "Ez dago kopiatu daitekeen fitxategi eta/edo karpetarik." + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "Helburuko karpeta:" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "Kopiatu" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "Ez dago tamaina aldatu dezakeen irudirik." + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "Ondoko irudien tamaina aldatuko da:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "" +"Argazkitxo aukera bat hautatu edo tamaina aldatzeko parametroak ezarri:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "" +"Kontuz: Irudien tamaina aldatzean jatorrizkoak galduko dira. Lehenbizi " +"jatorrizkoen kopia egin zenezake." + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "Tamaina aldatu" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." +msgstr "" +"Zure kontuak ez du hautatutako fitxategi eta/edo karpeta guztiak mugitzeko " +"baimenik." + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "Ez dago mugitu daitekeen fitxategi edo/eta karpetarik." + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "Mugitu" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "Zure kontuak ez du hautatutako fitxategiak berrizendatzeko baimenik." + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "Ez dago berrizendatu daitekeen fitxategirik." + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "Berrizendatu" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "Karpeta gurasora joan" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "Uneko karpetaren xehetasunak aldatu" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "Aldatu" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "Bilatu" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "Ezabatu" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "Karpeta berri bat sortzen du" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "Karpeta berria" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "Izena" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "Jabea" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "'%(item_label)s' karpetaren xehetasunak aldatu" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "" +msgstr[1] "" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "" +msgstr[1] "" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "Fitxategi hau aukeratu" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "'%(item_label)s'(r)en xehetasunak aldatu" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "Baimenak" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "ezgaituta" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "gaituta" + +#: templates/admin/filer/folder/directory_table_list.html:144 +#, fuzzy +#| msgid "Move selected files to clipboard" +msgid "URL copied to clipboard" +msgstr "Hautatutako fitxategiak arbelara mugitu" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "Igo" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "aurrekoa" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "hurrengoa" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "Berria gehitu" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "Zuzendu azpiko errorea mesedez." +msgstr[1] "Zuzendu azpiko erroreak mesedez." + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "Gorde" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "Arbela" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "Elementu guztiak hemen itsatsi" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "Arbeleko fitxategi guztiak hona mugitu:" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "arbela hutsik dago" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "igotzean errorea" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "topatuta" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "eta" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "bilaketa ezeztatu" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "Garbitu" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "hautatutako fitxategirik ez" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "Bilatu" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "" + +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/fa/LC_MESSAGES/django.mo b/filer/locale/fa/LC_MESSAGES/django.mo new file mode 100644 index 000000000..aed0b0b26 Binary files /dev/null and b/filer/locale/fa/LC_MESSAGES/django.mo differ diff --git a/filer/locale/fa/LC_MESSAGES/django.po b/filer/locale/fa/LC_MESSAGES/django.po new file mode 100644 index 000000000..964b88a0c --- /dev/null +++ b/filer/locale/fa/LC_MESSAGES/django.po @@ -0,0 +1,1045 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Dimacodev Team ddmc.ir , 2025 +# Translators: +# Translators: +# Fariman Ghaedi , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Fariman Ghaedi , 2019\n" +"Language-Team: Persian (http://app.transifex.com/divio/django-filer/language/" +"fa/)\n" +"Language: fa\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" + +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "شما مجوز آپلود فایل ها را ندارید." + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "پوشه ای برای آپلود یافت نشد. لطفاً صفحه را رفرش کرده و دوباره تلاش کنید" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "استفاده از این پوشه امکان پذیر نیست، دسترسی رد شد. لطفاً پوشه دیگری انتخاب کنید." + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "پیشرفته" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "آدرس کانونی" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" +"برای اینکه بتوانید روی آیتم ها اقداماتی انجام دهید ابتدا باید آیتم ها را " +"انتخاب کنید. هیچ آیتمی تغییر نکرد." + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "%(total_count)s انتخاب شده" +msgstr[1] "همه %(total_count)s انتخاب شده" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "لیست دایرکتوری برای %(folder_name)s" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "0 از %(cnt)s انتخاب شده" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "هیچ اقدامی انتخاب نشده است." + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "%(count)d فایل با موفقیت به کلیپ برد منتقل شد." + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "انتقال فایل های انتخاب شده به کلیپ برد" + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "مجوزهای %(count)d فایل با موفقیت غیرفعال شد." + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "مجوزهای %(count)d فایل با موفقیت فعال شد." + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "فعال کردن مجوزها برای فایل های انتخاب شده" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "غیرفعال کردن مجوزها برای فایل های انتخاب شده" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "%(count)d فایل و/یا پوشه با موفقیت حذف شد." + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "امکان حذف فایل ها و/یا پوشه ها وجود ندارد" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "آیا مطمئن هستید؟" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "حذف فایل ها و/یا پوشه ها" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "حذف فایل ها و/یا پوشه های انتخاب شده" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "پوشه هایی با نام %s در مقصد انتخاب شده از قبل وجود دارند" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "%(count)d فایل و/یا پوشه با موفقیت به پوشه '%(destination)s' منتقل شد." + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "انتقال فایل ها و/یا پوشه ها" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "انتقال فایل ها و/یا پوشه های انتخاب شده" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "%(count)d فایل با موفقیت تغییر نام داده شد." + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "تغییر نام فایل ها" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "%(count)d فایل و/یا پوشه با موفقیت به پوشه '%(destination)s' کپی شد." + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "کپی فایل ها و/یا پوشه ها" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "کپی فایل ها و/یا پوشه های انتخاب شده" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "%(count)d تصویر با موفقیت تغییر اندازه داده شد." + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "تغییر اندازه تصاویر" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "تغییر اندازه تصاویر انتخاب شده" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "پسوندی که به نام فایل های کپی شده اضافه خواهد شد." + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "پسوند باید بخشی معتبر، ساده و با حروف کوچک از نام فایل باشد، مانند \"%(valid)s\"." + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "کلید مقدار فرمت تغییر نام ناشناخته \"%(key)s\"." + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "فرمت تغییر نام نامعتبر: %(error)s." + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "گزینه تصویر بندانگشتی" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "عرض" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "ارتفاع" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "برش" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "بزرگنمایی" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "باید گزینه تصویر بندانگشتی یا پارامترهای تغییر اندازه انتخاب شود." + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "موقعیت موضوع" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "موقعیت موضوع اصلی صحنه. فرمت: \"x,y\"." + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "فرمت موقعیت موضوع نامعتبر است. " + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "موقعیت موضوع خارج از تصویر است. " + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "ورودی شما: \"{subject_location}\". " + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "چه کسی" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "چه چیزی" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "پوشه با این نام از قبل وجود دارد." + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "فایلر" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "کتابخانه رسانه" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "متن جایگزین پیش‌فرض" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "عنوان پیش‌فرض" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "موقعیت موضوع" + +#: models/abstract.py:91 +msgid "image" +msgstr "تصویر" + +#: models/abstract.py:92 +msgid "images" +msgstr "تصاویر" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" +"فرمت تصویر تشخیص داده نشد یا اندازه تصویر از حد مجاز %(max_pixels)d میلیون پیکسل " +"دو برابر یا بیشتر است. قبل از آپلود مجدد، فرمت فایل را بررسی کنید یا تصویر را " +"به اندازه %(width)d x %(height)d پیکسل یا کمتر تغییر اندازه دهید." + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" +"اندازه تصویر (%(pixels)d میلیون پیکسل) از حد مجاز %(max_pixels)d میلیون پیکسل " +"فراتر رفته است. قبل از آپلود مجدد، تصویر را به اندازه %(width)d x %(height)d " +"پیکسل یا کمتر تغییر اندازه دهید." + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "کاربر" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "فایل ها" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "کلیپ برد" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "کلیپ بردها" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "فایل" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "آیتم کلیپ برد" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "آیتم های کلیپ برد" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "پوشه" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "اندازه فایل" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "sha1" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "دارای تمام داده های اجباری است" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "نام فایل اصلی" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "نام" + +#: models/filemodels.py:116 +msgid "description" +msgstr "توضیحات" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "مالک" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "آپلود شده در" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "تغییر یافته در" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "مجوزها غیرفعال شده" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "بررسی هرگونه مجوز برای این فایل را غیرفعال کنید. فایل برای همه به صورت عمومی قابل دسترسی خواهد بود." + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "والد" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "ایجاد شده در" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "پوشه" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "پوشه ها" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "همه آیتم ها" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "فقط این آیتم" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "این آیتم و تمام فرزندان" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "به ارث بردن" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "اجازه دادن" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "رد کردن" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "نوع" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "گروه" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "همه" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "می تواند بخواند" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "می تواند ویرایش کند" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "می تواند فرزند اضافه کند" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "مجوز پوشه" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "مجوزهای پوشه" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "پوشه نمی تواند با نوع \"همه آیتم ها\" انتخاب شود." + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "هنگامی که نوع \"همه آیتم ها\" نیست، باید پوشه انتخاب شود." + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "کاربر یا گروه نمی تواند همراه با \"همه\" انتخاب شود." + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "حداقل یکی از کاربر، گروه یا \"همه\" باید انتخاب شود." + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "همه پوشه ها" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "مسیر منطقی" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "کاربر: {user}" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "گروه: {group}" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "همه" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "ویرایش" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "خواندن" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "افزودن فرزند" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "تاریخ گرفته شده" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "نویسنده" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "همیشه باید اعتبار نویسنده منتشر شود" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "همیشه باید حق چاپ منتشر شود" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "عرض بر حسب پیکسل." + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "ارتفاع بر حسب پیکسل." + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "گزینه های تصویر بندانگشتی" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "آپلودهای مرتب نشده" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "فایل های با متادیتای از دست رفته" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "ریشه" + +#: settings.py:273 +msgid "Show table view" +msgstr "نمایش نمای جدولی" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "نمایش نمای بندانگشتی" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "اجرای عمل انتخاب شده" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "برو" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "برای انتخاب اشیاء در تمام صفحات اینجا کلیک کنید" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "انتخاب همه %(total_count)s فایل ها و/یا پوشه ها" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "پاک کردن انتخاب" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "بازگشت به صفحه اصلی مدیریت" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "خانه" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "بازگشت به برنامه فایلر" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "بازگشت به پوشه ریشه" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "بازگشت به پوشه '%(folder_name)s'" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "تکرارها" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" +"حذف فایل ها و/یا پوشه های انتخاب شده منجر به حذف اشیاء مرتبط می شود، اما حساب " +"شما مجوز حذف انواع زیر از اشیاء را ندارد:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "" +"حذف فایل ها و/یا پوشه های انتخاب شده مستلزم حذف اشیاء محافظت شده مرتبط زیر است:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "" +"آیا مطمئن هستید که می خواهید فایل ها و/یا پوشه های انتخاب شده را حذف کنید؟ همه " +"اشیاء زیر و آیتم های مرتبط با آنها حذف خواهند شد:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "خیر، مرا برگردان" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "بله، مطمئنم" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "تاریخچه" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "مشاهده در سایت" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "بازگشت به" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "صفحه اصلی مدیریت" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "آیکون پوشه" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." +msgstr "حساب شما مجوز کپی کردن همه فایل ها و/یا پوشه های انتخاب شده را ندارد." + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "مرا برگردان" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "هیچ پوشه مقصدی در دسترس نیست." + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "هیچ فایل و/یا پوشه ای برای کپی کردن در دسترس نیست." + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "فایل ها و/یا پوشه های زیر به یک پوشه مقصد کپی خواهند شد (ساختار درختی آنها حفظ می شود):" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "پوشه مقصد:" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "کپی" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "کپی کردن فایل ها به همان پوشه مجاز نیست" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "حساب شما مجوز تغییر اندازه همه تصاویر انتخاب شده را ندارد." + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "هیچ تصویری برای تغییر اندازه در دسترس نیست." + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "تصاویر زیر تغییر اندازه داده خواهند شد:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "یک گزینه تصویر بندانگشتی موجود را انتخاب کنید یا پارامترهای تغییر اندازه را وارد کنید:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "" +"هشدار: تصاویر در جای خود تغییر اندازه داده می شوند و نسخه های اصلی از بین می " +"روند. شاید بهتر است ابتدا یک کپی از آنها تهیه کنید تا نسخه های اصلی حفظ شوند." + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "تغییر اندازه" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." +msgstr "حساب شما مجوز جابجایی همه فایل ها و/یا پوشه های انتخاب شده را ندارد." + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "هیچ فایل و/یا پوشه ای برای جابجایی در دسترس نیست." + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "فایل ها و/یا پوشه های زیر به یک پوشه مقصد منتقل خواهند شد (ساختار درختی آنها حفظ می شود):" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "انتقال" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "انتقال فایل ها به همان پوشه مجاز نیست" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "حساب شما مجوز تغییر نام همه فایل های انتخاب شده را ندارد." + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "هیچ فایلی برای تغییر نام در دسترس نیست." + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "فایل های زیر تغییر نام داده خواهند شد (در پوشه های خود باقی می مانند و نام فایل اصلی حفظ می شود، فقط نام نمایش داده شده تغییر می کند):" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "تغییر نام" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "بازگشت به پوشه والد" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "تغییر جزئیات پوشه فعلی" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "تغییر" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "برای جستجوی عبارت وارد شده اینجا کلیک کنید" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "جستجو" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "بستن" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "محدودیت" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "برای محدود کردن جستجو به پوشه فعلی آن را بررسی کنید" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "محدود کردن جستجو به پوشه فعلی" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "حذف" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "افزودن یک پوشه جدید" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "پوشه جدید" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "بارگذاری فایل‌ها" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "ابتدا باید یک پوشه انتخاب کنید" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "نام" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "مالک" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "اندازه" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "عملیات" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "تغییر جزئیات پوشه '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "%(counter)s پوشه" +msgstr[1] "%(counter)s پوشه" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "%(counter)s فایل" +msgstr[1] "%(counter)s فایل" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "تغییر جزئیات پوشه" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "حذف پوشه" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "انتخاب این فایل" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "تغییر جزئیات '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "مجوزها" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "غیرفعال" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "فعال" + +#: templates/admin/filer/folder/directory_table_list.html:144 +#, fuzzy +#| msgid "Move selected files to clipboard" +msgid "URL copied to clipboard" +msgstr "آدرس URL به کلیپ‌بورد کپی شد" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "آدرس اصلی '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "دانلود '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "حذف فایل" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "فایل‌ها را اینجا رها کنید یا از دکمه «بارگذاری فایل‌ها» استفاده کنید" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "فایل خود را برای بارگذاری اینجا رها کنید:" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "بارگذاری" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "لغو" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "بارگذاری موفقیت‌آمیز بود!" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "بارگذاری لغو شد!" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "قبلی" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "صفحه %(number)s از %(num_pages)s." + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "بعدی" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "انتخاب همه %(total_count)s" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "انتخاب همه" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "فایل‌ها" diff --git a/filer/locale/fi/LC_MESSAGES/django.mo b/filer/locale/fi/LC_MESSAGES/django.mo new file mode 100644 index 000000000..984dc53b7 Binary files /dev/null and b/filer/locale/fi/LC_MESSAGES/django.mo differ diff --git a/filer/locale/fi/LC_MESSAGES/django.po b/filer/locale/fi/LC_MESSAGES/django.po new file mode 100644 index 000000000..35fc907e0 --- /dev/null +++ b/filer/locale/fi/LC_MESSAGES/django.po @@ -0,0 +1,1259 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +# Niklas Jerva , 2016 +# Teemu Gratschev , 2022 +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Teemu Gratschev , 2022\n" +"Language-Team: Finnish (http://app.transifex.com/divio/django-filer/language/" +"fi/)\n" +"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" + +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "" + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "Edistyneet asetukset" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "sääntöjenmukainen URL" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" +"Toiminnon suorittamiseksi pitää valita kohteita. Yhtäänkohdetta ei ole " +"valittu." + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "%(total_count)s valittu" +msgstr[1] "Kaikki %(total_count)s valittu" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "Hakemistolistaus kansiolle %(folder_name)s" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "0 / %(cnt)s valittu" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "Toimintoa ei ole valittu." + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "%(count)d tiedostoa siirretty leikepöydälle." + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "Siirrä valitut tiedostot leikepöydälle" + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "%(count)d tiedoston käyttöoikeudet poistettu käytöstä." + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "Käyttöoikeudet otettu käyttöön %(count)d tiedostolle." + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "Ota käyttöoikeudet käyttöön valituille tiedostoille" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "Poista käyttöoikeudet käytöstä valituista tiedostoista" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "%(count)d tiedostoa ja/tai kansiota poistettu." + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "Kansioita ja/tai tiedostoja ei voida poistaa" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "Oletko varma?" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "Poista tiedostot ja/tai kansiot" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "Poista valitut tiedostot ja/tai kansiot" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "%s niminen kansio on jo valitussa kohteessa" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" +"%(count)d tiedostoa ja/tai kansiota siirretty kansioon '%(destination)s'." + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "Siirrä tiedostot ja/tai kansiot" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "Siirrä valitut tiedostot ja/tai kansiot" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "%(count)d tiedostoa nimetty uudelleen." + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "Nimeä tiedostot uudelleen" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" +"%(count)d tiedostoa ja/tai kansiota kopioitu kansioon '%(destination)s'." + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "Kopioi tiedostot ja/tai kansiot" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "Kopioi valitut tiedostot ja/tai kansiot" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "%(count)d kuvan kokoa muutettu." + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "Muuta kuvien kokoa" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "Muuta valittujen kuvien kokoa" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "Pääte, joka lisätään kopioitujen tiedostojen nimiin." + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "" +"Päätteen tulee olla käypä, yksinkertainen ja pienellä kirjoitettu osa " +"tiedostonimeä, esim. \"%(valid)s\"." + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "Tuntematon uudelleennimeämisarvo \"%(key)s\"." + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "Virheellinen uudelleennimeämismuoto: %(error)s." + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "pikkukuvan asetus" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "leveys" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "korkeus" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "rajaus" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "suurenna" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "Pikkukuvan asetus tai koon muuttamisen parametrit tulee valita." + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "Kohteen sijainti" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "Kuvan pääkohteen sijainti. Muoto: \"x,y\"." + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "Virheellinen kohteen sijainnin muoto." + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "Kohteen sijainti kuvan ulkopuolella." + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "Syöttösi: \"{subject_location}\"." + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "Saman niminen kansio on jo olemassa." + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "Filer" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "Mediakirjasto" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "oletus alt-teksti" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "oletuskuvateksti" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "kohteen sijainti" + +#: models/abstract.py:91 +msgid "image" +msgstr "kuva" + +#: models/abstract.py:92 +msgid "images" +msgstr "kuvat" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "käyttäjä" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "tiedostot" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "leikepöytä" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "leikepöydät" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "tiedosto" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "leikepöydän kohde" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "leikepöydän kohteet" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "kansio" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "tiedostokoko" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "sha1" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "sisältää kaikki pakolliset tiedot" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "alkuperäinen tiedostonimi" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "nimi" + +#: models/filemodels.py:116 +msgid "description" +msgstr "kuvaus" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "omistaja" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "ladattu" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "muokattu" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "Käyttöoikeudet pois käytöstä" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" +"Poista käyttöoikeuksien tarkistus tältä tiedostolta. Tiedosto näkyy " +"julkisena kaikille." + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "luotu" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "Kansio" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "Kansiot" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "kaikki kohteet" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "vain tämä kohde" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "tämä kohde ja kaikki lapset" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "salli" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "kiellä" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "tyyppi" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "ryhmä" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "kaikki" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "saa lukea" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "saa muokata" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "saa lisätä lapsia" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "kansion käyttöoikeus" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "kansion käyttöoikeudet" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "" + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "päivämäärä" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "tekijä" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "tekijän tiedot on aina julkaistava" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "tekijänoikeustiedot on aina julkaistava" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "leveys pikseleinä." + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "korkeus pikseleinä." + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "pikkukuvan asetukset" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "Järjestelemättömät lataukset" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "tiedostot ilman metadataa" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "juuri" + +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "Suorita valittu toiminto" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "Suorita" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "Valitse kaikki kohteet kaikilta sivuilta" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "Valitse kaikki %(total_count)s tiedostoa ja/tai kansiota" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "Tyhjennä valinta" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "Palaa hallinnan etusivulle" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "Etusivu" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "Palaa Fileriin" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "Palaa juurikansioon" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "Palaa kansioon '%(folder_name)s'" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "Kaksoiskappaleet" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" +"Valittujen tiedostojen ja/tai kansioiden poistaminen vaatii liittyvien " +"objektien poistamista, mutta käyttöoikeutesi eivät riitäseuraavien " +"objektityyppien poistamiseen:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "" +"Valittujen tiedostojen ja/tai kansioiden poistaminen vaatisi seuraavien " +"suojattujen liittyvien objektien poistamista:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "" +"Oletko varma, että haluat poistaa valitut tiedostot ja/tai kansiot? Kaikki " +"seuraavat objektit ja niihin liittyvät kohteet poistetaan:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "Ei, vie minut takaisin" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "Kyllä, olen varma" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "Historia" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "Näytä sivustolla" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "Palaa kohteeseen" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "hallinnan etusivu" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "Kansion kuvake" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." +msgstr "" +"Käyttöoikeutesi eivät riitä kaikkien valittujen tiedostojen ja/tai " +"kansioidenkopioimiseen." + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "Vie minut takaisin" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "Kohdekansioita ei ole saatavilla." + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "Kopioitavia tiedostoja ja/tai kansioita ei ole saatavilla." + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "" +"Seuraavat tiedostot ja/tai kansiot kopioidaan kohdekansioon (säilyttäen " +"puurakenteen):" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "Kohdekansio:" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "Kopioi" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "Tiedostojen kopiointi samaan kansioon ei ole sallittu" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "" +"Käyttöoikeutesi eivät riitä kaikkien valittujen kuvien koon muuttamiseen." + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "Kuvia, joiden kokoa voisi muuttaa ei ole saatavilla." + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "Seuraavien kuvien kokoa muutetaan:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "Valitse olemassaolevat pikkukuvan asetukset tai syötä kokoparametrit:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "" +"Varoitus: Kuvien kokoa muuttaessa alkuperäiset versiot menetetään. On hyvä " +"idea tehdä kuvista ensin kopiot alkuperäisten säilyttämiseksi." + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "Muuta kokoa" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." +msgstr "" +"Käyttöoikeutesi eivät riitä kaikkien valittujen tiedostojen ja/tai " +"kansioidensiirtämiseen." + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "Siirrettäviä tiedostoja ja/tai kansioita ei ole saatavilla." + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "" +"Seuraavat tiedostot ja/tai kansiot siirretään kohdekansioon (säilyttäen " +"niiden puurakenne):" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "Siirrä" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "Tiedostojen siirto samaan kansioon ei ole sallittua" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "" +"Käyttöoikeutesi eivät riitä kaikkien valittujen tiedostojen " +"uudelleennimeämiseen." + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "Uudelleennimettäviä tiedostoja ei ole saatavilla." + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "" +"Seuraavat tiedostot uudelleennimetään (ne pysyvät kansioissaan ja " +"alkuperäiset tiedostonimet säilytetään, vain näytettävä tiedostonimi " +"muutetaan):" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "Uudelleennimeä" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "Palaa ylempään kansioon" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "Muuta nykyisen kansion tietoja" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "Muuta" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "Valitse suorittaaksesi haun annetulla hakusanalla" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "Hae" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "Sulje" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "Raja" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "Valitse rajoittaaksesi haun nykyiseen kansioon" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "Rajoita haku nykyiseen kansioon" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "Poista" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "Lisää uusi kansio" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "Uusi kansio" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "Lataa tiedostoja" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "Sinun tulee valita kansio ensin" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "Nimi" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "Omistaja" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "Koko" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "Toiminto" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "Muuta kansion '%(item_label)s' tietoja" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "%(counter)s kansio" +msgstr[1] "%(counter)s kansiota" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "%(counter)s tiedosto" +msgstr[1] "%(counter)s tiedostoa" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "Muuta kansion tietoja" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "Poista kansio" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "Valitse tämä tiedosto" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "Muuta kohteen '%(item_label)s' tietoja" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "Käyttöoikeudet" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "pois käytöstä" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "käytössä" + +#: templates/admin/filer/folder/directory_table_list.html:144 +#, fuzzy +#| msgid "Move selected files to clipboard" +msgid "URL copied to clipboard" +msgstr "Siirrä valitut tiedostot leikepöydälle" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "Canonical-osoite '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "Lataa '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "Poista tiedosto" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "Pudota tiedostoja tähän tai käytä \"Lataa tiedostoja\" painiketta" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "Pudota tiedostosi:" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "Siirrä palvelimelle" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "peruuta" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "Lataus onnistui!" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "Lataus peruttu!" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "edellinen" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "Sivu %(number)s/%(num_pages)s" + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "seuraava" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "Valitse kaikki %(total_count)s" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "Lisää uusi" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "Django-sivuston ylläpito" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "Ole hyvä ja korjaa allaoleva virhe." +msgstr[1] "Ole hyvä ja korjaa allaolevat virheet." + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "Tallenna" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "Leikepöytä" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "Liitä kaikki kohteet tähän" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "Siirrä kaikki leikepöydällä olevat tiedostot" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "Tyhjä leikepöytä" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "leikepöytä on tyhjä" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "siirto epäonnistui" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "Tyyppi" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "Tiedostokoko" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "Muokattu" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "Luotu" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "löytyi" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "ja" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "peruuta haku" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "Tyhjennä" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "tai pudota tiedostosi tähän" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "yhtään tiedostoa ei ole valittu" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "Haku" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "Valitse tiedosto" + +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/fr/LC_MESSAGES/django.mo b/filer/locale/fr/LC_MESSAGES/django.mo index 602810612..9936407bf 100644 Binary files a/filer/locale/fr/LC_MESSAGES/django.mo and b/filer/locale/fr/LC_MESSAGES/django.mo differ diff --git a/filer/locale/fr/LC_MESSAGES/django.po b/filer/locale/fr/LC_MESSAGES/django.po index 662e7b320..5e56554c3 100644 --- a/filer/locale/fr/LC_MESSAGES/django.po +++ b/filer/locale/fr/LC_MESSAGES/django.po @@ -1,935 +1,1249 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: -# Bertrand Bordage , 2012. -# Marion Balensi , 2012. +# Translators: +# Translators: +# Assma Buifruri , 2017 +# Bertrand Bordage , 2012-2013 +# Sylvain Chiron , 2016 +# Corentin Bettiol, 2023 +# Jason Gass Martinez , 2016 +# Marion Balensi , 2012 +# Nicolas PASCAL , 2019 msgid "" msgstr "" -"Project-Id-Version: django-filer\n" +"Project-Id-Version: django Filer\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-07-13 19:10+0200\n" -"PO-Revision-Date: 2012-09-03 20:11+0100\n" -"Last-Translator: Stefan Foulis \n" -"Language-Team: French (http://www.transifex.com/projects/p/django-filer/" -"language/fr/)\n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Corentin Bettiol, 2023\n" +"Language-Team: French (http://app.transifex.com/divio/django-filer/language/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fr\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" -#: views.py:103 -msgid "Folder with this name already exists." -msgstr "Il existe déjà un dossier avec ce nom." +#: admin/clipboardadmin.py:17 +#| msgid "" +#| "ccount doesn't have permissions to rename all of the selected files." +msgid "You do not have permission to upload files." +msgstr "Vous n'avez pas la permission d'héberger des fichiers." + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "Dossier d'hébergement introuvable, rafraîchissez la page et réessayez." -#: admin/fileadmin.py:41 +#: admin/clipboardadmin.py:20 +msgid "" +"Can't use this folder, Permission Denied. Please select another folder." +msgstr "Utilisation du dossier impossible : Permissions insuffisantes. Sélectionnez un autre dossier." + +#: admin/fileadmin.py:73 msgid "Advanced" msgstr "Avancé" -#: admin/folderadmin.py:324 admin/folderadmin.py:427 +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "URL canonique" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 msgid "" "Items must be selected in order to perform actions on them. No items have " "been changed." -msgstr "" -"Des éléments doivent être selectionnés pour effectuer des actions sur eux. " -"Aucun élément n'a été modifié." +msgstr "Des éléments doivent être sélectionnés pour effectuer les actions. Aucun élément n'a été modifié." -#: admin/folderadmin.py:344 +#: admin/folderadmin.py:434 #, python-format msgid "%(total_count)s selected" msgid_plural "All %(total_count)s selected" msgstr[0] "%(total_count)s sélectionné" msgstr[1] "Tous les %(total_count)s sélectionnés" +msgstr[2] "Tous les %(total_count)s sélectionnés" -#: admin/folderadmin.py:377 +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "Liste du répertoire pour %(folder_name)s" + +#: admin/folderadmin.py:475 #, python-format msgid "0 of %(cnt)s selected" msgstr "0 sur %(cnt)s sélectionné" -#: admin/folderadmin.py:456 +#: admin/folderadmin.py:612 msgid "No action selected." msgstr "Pas d'action sélectionnée." -#: admin/folderadmin.py:497 +#: admin/folderadmin.py:664 #, python-format msgid "Successfully moved %(count)d files to clipboard." msgstr "%(count)d fichiers déplacés avec succès vers le presse-papiers." -#: admin/folderadmin.py:503 +#: admin/folderadmin.py:669 msgid "Move selected files to clipboard" -msgstr "Déplacer les fichiers sélectionnés vers le presse-papiers." +msgstr "Déplacer les fichiers sélectionnés vers le presse-papiers" -#: admin/folderadmin.py:537 +#: admin/folderadmin.py:709 #, python-format msgid "Successfully disabled permissions for %(count)d files." msgstr "Permissions désactivées avec succès pour %(count)d fichiers." -#: admin/folderadmin.py:541 +#: admin/folderadmin.py:711 #, python-format msgid "Successfully enabled permissions for %(count)d files." msgstr "Permissions activées avec succès pour %(count)d fichiers." -#: admin/folderadmin.py:550 +#: admin/folderadmin.py:719 msgid "Enable permissions for selected files" msgstr "Activer les permissions pour les fichiers sélectionnés." -#: admin/folderadmin.py:555 +#: admin/folderadmin.py:725 msgid "Disable permissions for selected files" msgstr "Désactiver les permissions pour les fichiers sélectionnés." -#: admin/folderadmin.py:623 +#: admin/folderadmin.py:789 #, python-format msgid "Successfully deleted %(count)d files and/or folders." msgstr "%(count)d fichiers et/ou dossiers supprimés avec succès." -#: admin/folderadmin.py:630 +#: admin/folderadmin.py:794 msgid "Cannot delete files and/or folders" msgstr "Impossible de supprimer les fichiers et/ou dossiers." -#: admin/folderadmin.py:632 +#: admin/folderadmin.py:796 msgid "Are you sure?" msgstr "Êtes-vous sûr(e) ?" -#: admin/folderadmin.py:637 +#: admin/folderadmin.py:802 msgid "Delete files and/or folders" -msgstr "Supprimer les fichiers et/ou dossiers." +msgstr "Supprimer les fichiers et/ou dossiers" -#: admin/folderadmin.py:656 +#: admin/folderadmin.py:823 msgid "Delete selected files and/or folders" -msgstr "Supprimer les fichiers et/ou dossiers sélectionnés." +msgstr "Supprimer les fichiers et/ou dossiers sélectionnés" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "Des dossiers nommés %s existent déjà dans la destination sélectionnée" -#: admin/folderadmin.py:771 +#: admin/folderadmin.py:934 #, python-format msgid "" "Successfully moved %(count)d files and/or folders to folder " "'%(destination)s'." -msgstr "" -"%(count)d fichiers et/ou dossiers déplacés avec succès vers le dossier « " -"%(destination)s »." +msgstr "%(count)d fichiers et/ou dossiers déplacés avec succès vers le dossier « %(destination)s »." -#: admin/folderadmin.py:778 admin/folderadmin.py:780 +#: admin/folderadmin.py:942 admin/folderadmin.py:944 msgid "Move files and/or folders" -msgstr "Déplacer les fichers et/ou dossiers." +msgstr "Déplacer les fichiers et/ou dossiers" -#: admin/folderadmin.py:797 +#: admin/folderadmin.py:959 msgid "Move selected files and/or folders" -msgstr "Déplacer les fichiers et/ou dossiers sélectionnés." +msgstr "Déplacer les fichiers et/ou dossiers sélectionnés" -#: admin/folderadmin.py:854 +#: admin/folderadmin.py:1016 #, python-format msgid "Successfully renamed %(count)d files." msgstr "%(count)d fichiers renommés avec succès." -#: admin/folderadmin.py:862 admin/folderadmin.py:864 admin/folderadmin.py:881 +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 msgid "Rename files" -msgstr "Renommer les fichiers." +msgstr "Renommer les fichiers" -#: admin/folderadmin.py:975 +#: admin/folderadmin.py:1137 #, python-format msgid "" "Successfully copied %(count)d files and/or folders to folder " "'%(destination)s'." -msgstr "" -"%(count)d fichiers et/dossiers copiés avec succès dans le dossier « " -"%(destination)s »." +msgstr "%(count)d fichiers et/dossiers copiés avec succès dans le dossier « %(destination)s »." -#: admin/folderadmin.py:989 admin/folderadmin.py:991 +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 msgid "Copy files and/or folders" -msgstr "Copier les fichiers et/ou dossiers." +msgstr "Copier les fichiers et/ou dossiers" -#: admin/folderadmin.py:1010 +#: admin/folderadmin.py:1174 msgid "Copy selected files and/or folders" -msgstr "Copier les fichiers et/ou dossiers sélectionnés." +msgstr "Copier les fichiers et/ou dossiers sélectionnés" -#: admin/folderadmin.py:1105 +#: admin/folderadmin.py:1279 #, python-format msgid "Successfully resized %(count)d images." msgstr "%(count)d images redimensionnées avec succès." -#: admin/folderadmin.py:1113 admin/folderadmin.py:1115 +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 msgid "Resize images" -msgstr "Redimensionner les images." +msgstr "Redimensionner les images" -#: admin/folderadmin.py:1133 +#: admin/folderadmin.py:1303 msgid "Resize selected images" -msgstr "Redimensionner les images sélectionnées." +msgstr "Redimensionner les images sélectionnées" -#: admin/forms.py:26 +#: admin/forms.py:24 msgid "Suffix which will be appended to filenames of copied files." -msgstr "Suffixe qui sera ajouté aux noms des fichiers copiés." +msgstr "Suffixe qui sera ajouté au nom des fichiers copiés." -#: admin/forms.py:33 +#: admin/forms.py:31 #, python-format msgid "" "Suffix should be a valid, simple and lowercase filename part, like " "\"%(valid)s\"." -msgstr "" -"Le suffixe doit être une partie de nom de fichier simple et en minuscules, " -"comme \"%(valid)s\"." +msgstr "Le suffixe doit être une partie de nom de fichier valide, simple et en minuscules, comme « %(valid)s »." -#: admin/forms.py:54 +#: admin/forms.py:52 #, python-format msgid "Unknown rename format value key \"%(key)s\"." -msgstr "La valeur de la clé de formatage \"%(key)s\" est inconnue." +msgstr "La clé de formatage « %(key)s » est inconnue." -#: admin/forms.py:56 +#: admin/forms.py:54 #, python-format msgid "Invalid rename format: %(error)s." msgstr "Format de renommage non valide : %(error)s." -#: admin/forms.py:62 +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 msgid "thumbnail option" msgstr "option de miniature" -#: admin/forms.py:63 +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 msgid "width" msgstr "largeur" -#: admin/forms.py:64 +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 msgid "height" msgstr "hauteur" -#: admin/forms.py:65 +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 msgid "crop" msgstr "rogner" -#: admin/forms.py:66 +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 msgid "upscale" -msgstr "élargir" +msgstr "agrandir" -#: admin/forms.py:71 +#: admin/forms.py:79 msgid "Thumbnail option or resize parameters must be choosen." -msgstr "" -"Une option de miniature ou des paramètres de redimensionnement doivent être " -"choisis." - -#: admin/forms.py:73 -msgid "Resize parameters must be choosen." -msgstr "Des paramètres de redimensionnement doivent être choisis." +msgstr "Une option de miniature ou des paramètres de dimensionnement doivent être choisis." -#: admin/imageadmin.py:12 +#: admin/imageadmin.py:20 admin/imageadmin.py:112 msgid "Subject location" msgstr "Emplacement du sujet" -#: admin/imageadmin.py:13 -msgid "Location of the main subject of the scene." -msgstr "Emplacement du sujet principal de la scène." +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "Emplacement du sujet principal de la scène. Format : « x,y »." + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "Format d'emplacement de sujet invalide." + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "L'emplacement du sujet est en dehors de l'image." + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "Votre entrée : « {subject_location} »." + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "Qui" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "Quoi" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "Il existe déjà un dossier avec ce nom." + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "Filer" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "Bibliotèque multimedia" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "texte alternatif par défaut" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "légende par défaut" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "emplacement du sujet" + +#: models/abstract.py:91 +msgid "image" +msgstr "image" + +#: models/abstract.py:92 +msgid "images" +msgstr "images" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "Le format de l'image n'est pas reconnu, ou la taille de l'image dépasse la limite de%(max_pixels)d millions pixels deux fois ou plus. Avant d'envoyer l'image à nouveau, vérifiez le format de l'image, ou redimensionnez l'image afin qu'elle aie une résolution de %(width)d x %(height)d pixels ou moins." -#: models/clipboardmodels.py:9 models/foldermodels.py:236 +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "La taille de l'image (%(pixels)d millions de pixels) dépasse la limite de %(max_pixels)d millions de pixels. Avant d'envoyer l'image à nouveau, redimensionnez la pour qu'elle aie une résolution de %(width)d x %(height)d pixels ou moins." + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 msgid "user" msgstr "utilisateur" -#: models/clipboardmodels.py:11 models/filemodels.py:287 +#: models/clipboardmodels.py:17 models/filemodels.py:157 msgid "files" msgstr "fichiers" -#: models/clipboardmodels.py:34 models/clipboardmodels.py:40 +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 msgid "clipboard" msgstr "presse-papiers" -#: models/clipboardmodels.py:35 +#: models/clipboardmodels.py:25 msgid "clipboards" -msgstr "presses-papiers" +msgstr "presse-papiers" -#: models/clipboardmodels.py:39 models/filemodels.py:35 -#: models/filemodels.py:286 +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 msgid "file" -msgstr "fichiers" +msgstr "fichier" -#: models/clipboardmodels.py:44 +#: models/clipboardmodels.py:56 msgid "clipboard item" msgstr "élément du presse-papiers" -#: models/clipboardmodels.py:45 +#: models/clipboardmodels.py:57 msgid "clipboard items" msgstr "éléments du presse-papiers" -#: models/filemodels.py:33 templates/admin/filer/folder/change_form.html:9 -#: templates/admin/filer/folder/directory_listing.html:74 +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 #: templates/admin/filer/folder/new_folder_form.html:4 -#: templates/admin/filer/tools/clipboard/clipboard.html:26 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 msgid "folder" msgstr "dossier" -#: models/filemodels.py:36 +#: models/filemodels.py:81 msgid "file size" msgstr "taille du fichier" -#: models/filemodels.py:38 +#: models/filemodels.py:87 msgid "sha1" msgstr "sha1" -#: models/filemodels.py:40 +#: models/filemodels.py:94 msgid "has all mandatory data" msgstr "possède toutes les données nécessaires" -#: models/filemodels.py:42 +#: models/filemodels.py:100 msgid "original filename" msgstr "nom de fichier originel" -#: models/filemodels.py:44 models/foldermodels.py:99 +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 msgid "name" msgstr "nom" -#: models/filemodels.py:46 +#: models/filemodels.py:116 msgid "description" msgstr "description" -#: models/filemodels.py:50 +#: models/filemodels.py:125 models/foldermodels.py:108 msgid "owner" msgstr "propriétaire" -#: models/filemodels.py:52 models/foldermodels.py:105 +#: models/filemodels.py:129 models/foldermodels.py:116 msgid "uploaded at" -msgstr "transféré le" +msgstr "téléversé le" -#: models/filemodels.py:53 models/foldermodels.py:108 +#: models/filemodels.py:134 models/foldermodels.py:126 msgid "modified at" msgstr "modifié le" -#: models/filemodels.py:57 +#: models/filemodels.py:140 msgid "Permissions disabled" msgstr "Permissions désactivées" -#: models/filemodels.py:58 -msgid "Disable any permission checking for this " -msgstr "" +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "Désactiver la vérification des permissions pour ce fichier. Le fichier sera publiquement accessible à tout le monde." -#: models/foldermodels.py:107 +#: models/foldermodels.py:94 +msgid "parent" +msgstr "parent" + +#: models/foldermodels.py:121 msgid "created at" msgstr "créé le" -#: models/foldermodels.py:211 -#: templates/admin/filer/widgets/admin_folder.html:3 -#: templates/admin/filer/widgets/admin_folder.html:5 +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 msgid "Folder" msgstr "Dossier" -#: models/foldermodels.py:212 +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 msgid "Folders" msgstr "Dossiers" -#: models/foldermodels.py:227 +#: models/foldermodels.py:260 msgid "all items" msgstr "tous les éléments" -#: models/foldermodels.py:228 +#: models/foldermodels.py:261 msgid "this item only" msgstr "cet élément seulement" -#: models/foldermodels.py:229 +#: models/foldermodels.py:262 msgid "this item and all children" msgstr "cet élément et ses enfants" -#: models/foldermodels.py:233 +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "hériter" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "autoriser" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "refuser" + +#: models/foldermodels.py:280 msgid "type" msgstr "type" -#: models/foldermodels.py:239 +#: models/foldermodels.py:297 msgid "group" msgstr "groupe" -#: models/foldermodels.py:240 +#: models/foldermodels.py:304 msgid "everybody" msgstr "tous" -#: models/foldermodels.py:242 -msgid "can edit" -msgstr "peut éditer" - -#: models/foldermodels.py:243 +#: models/foldermodels.py:309 msgid "can read" msgstr "peut lire" -#: models/foldermodels.py:244 +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "peut éditer" + +#: models/foldermodels.py:325 msgid "can add children" msgstr "peut ajouter un enfant" -#: models/foldermodels.py:273 +#: models/foldermodels.py:333 msgid "folder permission" msgstr "permission du dossier" -#: models/foldermodels.py:274 +#: models/foldermodels.py:334 msgid "folder permissions" msgstr "permissions du dossier" -#: models/imagemodels.py:39 -msgid "date taken" -msgstr "date de prise de vue" +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "Le dossier ne peut pas être sélectionné avec le type \"tous les éléments\"." -#: models/imagemodels.py:42 -msgid "default alt text" -msgstr "texte alternatif par défaut" +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "Un dossier doit être sélectionné lorsque le type n'est pas \"tous les éléments\"." -#: models/imagemodels.py:43 -msgid "default caption" -msgstr "légende par défaut" +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "Un utilisateur ou un groupe ne peuvent être sélectionnés lorsque \"tout le monde\" est également sélectionné." -#: models/imagemodels.py:45 templates/image_filer/image.html:6 -msgid "author" -msgstr "auteur" +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "Au moins une option parmi un utilisateur, un groupe, ou \"tout le monde\" doit être sélectionnée." -#: models/imagemodels.py:47 -msgid "must always publish author credit" -msgstr "attribution à l'auteur toujours publiée" +#: models/foldermodels.py:360 +#| msgid "Folders" +msgid "All Folders" +msgstr "Tous les dossiers" -#: models/imagemodels.py:48 -msgid "must always publish copyright" -msgstr "copyright toujours publié" +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "Chemin logique" -#: models/imagemodels.py:50 -msgid "subject location" -msgstr "emplacement du sujet" +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "Utilisateur : {user}" -#: models/imagemodels.py:200 -msgid "image" -msgstr "image" +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "Groupe : {group}" -#: models/imagemodels.py:201 -msgid "images" -msgstr "images" +#: models/foldermodels.py:375 +#| msgid "everybody" +msgid "Everybody" +msgstr "Tout le monde" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "Modifier" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "Lire" + +#: models/foldermodels.py:390 +#| msgid "can add children" +msgid "Add children" +msgstr "Ajouter un sous-dossier" -#: models/virtualitems.py:45 -#: templates/admin/filer/tools/clipboard/clipboard.html:26 -msgid "unfiled files" -msgstr "Fichiers non classés" +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "date de prise de vue" -#: models/virtualitems.py:59 +#: models/imagemodels.py:25 +msgid "author" +msgstr "auteur" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "doit toujours publier l'attribution à l'auteur" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "doit toujours publier le droit d'auteur" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "largeur en pixels." + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "hauteur en pixels." + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "options de miniature" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "Téléversements non triés" + +#: models/virtualitems.py:73 msgid "files with missing metadata" -msgstr "fichiers aux métadonnées manquantes" +msgstr "fichiers avec des métadonnées manquantes" -#: models/virtualitems.py:73 templates/admin/filer/breadcrumbs.html:6 -#: templates/admin/filer/folder/change_form.html:9 -#: templates/admin/filer/folder/directory_listing.html:74 -#: templates/image_filer/image_export_form.html:10 +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 msgid "root" -msgstr "Dossier racine" +msgstr "racine" + +#: settings.py:273 +msgid "Show table view" +msgstr "Voir la vue en liste" + +#: settings.py:278 +#| msgid "thumbnail option" +msgid "Show thumbnail view" +msgstr "Voir la vue avec des miniatures" -#: templates/admin/filer/actions.html:4 +#: templates/admin/filer/actions.html:5 msgid "Run the selected action" msgstr "Exécuter l'action sélectionnée" -#: templates/admin/filer/actions.html:4 +#: templates/admin/filer/actions.html:5 msgid "Go" msgstr "Envoyer" -#: templates/admin/filer/actions.html:11 +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 msgid "Click here to select the objects across all pages" msgstr "Cliquez ici pour sélectionner tous les objets sur l'ensemble des pages" -#: templates/admin/filer/actions.html:11 +#: templates/admin/filer/actions.html:14 #, python-format msgid "Select all %(total_count)s files and/or folders" msgstr "Sélectionner tous les %(total_count)s fichiers et/ou dossiers" -#: templates/admin/filer/actions.html:13 +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 msgid "Clear selection" msgstr "Effacer la sélection" #: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 msgid "Go back to admin homepage" -msgstr "Retourner à la page d'accueil de l'administrateur." +msgstr "Retourner à la page d'accueil de l'administration" #: templates/admin/filer/breadcrumbs.html:4 -#: templates/admin/filer/folder/change_form.html:7 -#: templates/image_filer/image_export_form.html:7 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 msgid "Home" msgstr "Accueil" #: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 msgid "Go back to Filer app" msgstr "Revenir à l'application Filer" -#: templates/admin/filer/breadcrumbs.html:5 -#: templates/admin/filer/folder/change_form.html:8 -#: templates/image_filer/image_export_form.html:8 -msgid "Filer" -msgstr "Filer" - #: templates/admin/filer/breadcrumbs.html:6 -#: templates/image_filer/image_export_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:35 msgid "Go back to root folder" -msgstr "Retourner au dossier racine" +msgstr "Revenir au dossier racine" #: templates/admin/filer/breadcrumbs.html:8 -#: templates/admin/filer/breadcrumbs.html:11 -#: templates/admin/filer/folder/change_form.html:11 -#: templates/image_filer/image_export_form.html:12 -#: templates/image_filer/image_export_form.html:14 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 #, python-format msgid "Go back to '%(folder_name)s' folder" -msgstr "Retourner au dossier « %(folder_name)s »" +msgstr "Revenir au dossier « %(folder_name)s »" -#: templates/admin/filer/change_form.html:28 -msgid "duplicates" -msgstr "doublons" - -#: templates/admin/filer/delete_confirmation.html:13 -#, python-format -msgid "" -"Deleting the %(object_name)s '%(escaped_object)s' would result in deleting " -"related objects, but your account doesn't have permission to delete the " -"following types of objects:" -msgstr "" -"Supprimer l'objet %(object_name)s « %(escaped_object)s » provoquerait la " -"suppression d'objets liés, mais votre compte ne possède pas la permission de " -"supprimer les types d'objets suivants :" - -#: templates/admin/filer/delete_confirmation.html:21 -#, python-format -msgid "" -"Deleting the %(object_name)s '%(escaped_object)s' would require deleting the " -"following protected related objects:" -msgstr "" -"Supprimer l'objet %(object_name)s « %(escaped_object)s » provoquerait la " -"suppression des objets qui lui sont liés, mais votre compte ne possède pas " -"la permission de supprimer les types d'objets suivants :" - -#: templates/admin/filer/delete_confirmation.html:29 -#, python-format -msgid "" -"Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? " -"All of the following related items will be deleted:" -msgstr "" -"Voulez vous vraiment supprimer l'objet %(object_name)s « %(escaped_object)s " -"» ? Les éléments suivants sont liés à celui-ci et seront aussi supprimés :" - -#: templates/admin/filer/delete_confirmation.html:34 -#: templates/admin/filer/delete_selected_files_confirmation.html:45 -msgid "Yes, I'm sure" -msgstr "Oui, je suis sûr(e)." +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "Duplicatas" #: templates/admin/filer/delete_selected_files_confirmation.html:11 msgid "" "Deleting the selected files and/or folders would result in deleting related " "objects, but your account doesn't have permission to delete the following " "types of objects:" -msgstr "" -"Supprimer les fichier et/ou dossiers sélectionnés provoquerait la " -"suppression d'objets liés, mais votre compte ne possède pas la permission de " -"supprimer les types d'objets suivants :" +msgstr "Supprimer les fichiers et/ou dossiers sélectionnés devrait provoquer la suppression des objets liés, mais votre compte n'a pas les permissions nécessaires pour supprimer les types d'objets suivants :" #: templates/admin/filer/delete_selected_files_confirmation.html:19 msgid "" "Deleting the selected files and/or folders would require deleting the " "following protected related objects:" -msgstr "" -"Supprimer les fichiers et/ou dossiers provoquerait la suppression des " -"objetsliés protégés suivants :" +msgstr "Supprimer les fichiers et/ou dossiers provoquera la suppression des objets liés protégés suivants :" #: templates/admin/filer/delete_selected_files_confirmation.html:27 msgid "" "Are you sure you want to delete the selected files and/or folders? All of " "the following objects and their related items will be deleted:" -msgstr "" -"Voulez vous vraiment supprimer l'objet les fichiers et/ou dossiers " -"sélectionnés ? Les éléments suivants sont liés à celui-ci et seront aussi " -"supprimés :" +msgstr "Voulez-vous vraiment supprimer les fichiers et/ou dossiers sélectionnés ? Tous les objets suivants et leurs éléments liés seront supprimés :" -#: templates/admin/filer/folder/change_form.html:7 -#: templates/admin/filer/folder/change_form.html:8 -#: templates/admin/filer/folder/change_form.html:9 -#: templates/admin/filer/folder/directory_listing.html:74 -#: templates/image_filer/image_export_form.html:7 -#: templates/image_filer/image_export_form.html:8 -#: templates/image_filer/image_export_form.html:16 -msgid "Go back to" -msgstr "Retourner à" +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "Non, faites-moi revenir" -#: templates/admin/filer/folder/change_form.html:7 -#: templates/image_filer/image_export_form.html:7 -msgid "admin homepage" -msgstr "page d'accueil de l'administrateur" +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "Oui, je suis sûr" -#: templates/admin/filer/folder/change_form.html:22 -#: templates/admin/filer/image/change_form.html:9 +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 msgid "History" msgstr "Historique" +#: templates/admin/filer/file/change_form.html:37 #: templates/admin/filer/folder/change_form.html:23 -#: templates/admin/filer/image/change_form.html:10 +#: templates/admin/filer/image/change_form.html:37 msgid "View on site" msgstr "Voir sur le site" -#: templates/admin/filer/folder/change_form.html:35 -#: templates/admin/filer/folder/directory_listing.html:75 -#: templates/admin/filer/folder/directory_listing.html:85 -#: templates/admin/filer/folder/directory_table.html:23 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "Retourner à" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "page d'accueil de l'administrateur" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 msgid "Folder Icon" msgstr "Icône du dossier" -#: templates/admin/filer/folder/choose_copy_destination.html:12 +#: templates/admin/filer/folder/choose_copy_destination.html:23 msgid "" -"Your account doesn't have permissions to copy all of the selected files and/" -"or folders." -msgstr "" -"Votre compte n'a pas les permissions nécessaires pour copier tous lesfichers " -"et/ou dossiers sélectionnés." - -#: templates/admin/filer/folder/choose_copy_destination.html:15 -#: templates/admin/filer/folder/choose_move_destination.html:15 +"Your account doesn't have permissions to copy all of the selected files " +"and/or folders." +msgstr "Votre compte n'a pas les permissions nécessaires pour copier tous les fichiers et/ou dossiers sélectionnés." + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "Retour" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 msgid "There are no destination folders available." msgstr "Aucun dossier de destination disponible." -#: templates/admin/filer/folder/choose_copy_destination.html:18 +#: templates/admin/filer/folder/choose_copy_destination.html:35 msgid "There are no files and/or folders available to copy." -msgstr "Aucun fichier ou dossier n'estss disponible à copier." +msgstr "Aucun fichier ou dossier n'est disponible à copier." -#: templates/admin/filer/folder/choose_copy_destination.html:20 +#: templates/admin/filer/folder/choose_copy_destination.html:40 msgid "" "The following files and/or folders will be copied to a destination folder " "(retaining their tree structure):" -msgstr "" -"Les fichiers et/ou dossiers suivants seront copiés vers un dossier de " -"destination (en conservant leur arborescence) :" +msgstr "Les fichiers et/ou dossiers suivants seront copiés vers un dossier de destination (en conservant leur arborescence) :" -#: templates/admin/filer/folder/choose_copy_destination.html:32 -#: templates/admin/filer/folder/choose_move_destination.html:32 +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 msgid "Destination folder:" msgstr "Dossier de destination :" -#: templates/admin/filer/folder/choose_copy_destination.html:39 +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 msgid "Copy" msgstr "Copier" -#: templates/admin/filer/folder/choose_images_resize_options.html:12 +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "Il est impossible de copier des fichiers dans le même dossier" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 msgid "" "Your account doesn't have permissions to resize all of the selected images." -msgstr "" -"Votre compte na pas les permissions necessaires pour redimensionner toutes " -"les images sélectionnées." +msgstr "Votre compte na pas les permissions nécessaires pour redimensionner toutes les images sélectionnées." -#: templates/admin/filer/folder/choose_images_resize_options.html:15 +#: templates/admin/filer/folder/choose_images_resize_options.html:18 msgid "There are no images available to resize." msgstr "Il n'y a aucune image disponible à redimensionner." -#: templates/admin/filer/folder/choose_images_resize_options.html:17 +#: templates/admin/filer/folder/choose_images_resize_options.html:20 msgid "The following images will be resized:" msgstr "Les images suivantes seront redimensionnées :" -#: templates/admin/filer/folder/choose_images_resize_options.html:30 -msgid "Choose an existing thumbnail option or enter resize parameters:" -msgstr "" -"Choisissez une option de miniature ou entrez des paramètres de " -"redimensionnement :" - #: templates/admin/filer/folder/choose_images_resize_options.html:32 -msgid "Choose resize parameters:" -msgstr "Choisissez des paramètres de redimensionnement :" +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "Choisissez une option de miniature existante ou entrez des paramètres de redimensionnement :" -#: templates/admin/filer/folder/choose_images_resize_options.html:35 +#: templates/admin/filer/folder/choose_images_resize_options.html:36 msgid "" "Warning: Images will be resized in-place and originals will be lost. Maybe " "first make a copy of them to retain the originals." -msgstr "" -"Avertissement : Le redimensionnement des images écrasera les originaux. " -"Faites en éventuellement une copie afin de conserver les originaux." +msgstr "Avertissement : Les images seront redimensionnées en place et les originales seront perdues. Faites-en éventuellement une copie préalable afin de les conserver." -#: templates/admin/filer/folder/choose_images_resize_options.html:36 +#: templates/admin/filer/folder/choose_images_resize_options.html:39 msgid "Resize" msgstr "Redimensionner" -#: templates/admin/filer/folder/choose_move_destination.html:12 +#: templates/admin/filer/folder/choose_move_destination.html:35 msgid "" -"Your account doesn't have permissions to move all of the selected files and/" -"or folders." -msgstr "" -"Votre compte n'a pas les permissions nécessaires pour déplacer tous les " -"fichiers et/ou dossiers sélectionnés." +"Your account doesn't have permissions to move all of the selected files " +"and/or folders." +msgstr "Votre compte n'a pas les permissions nécessaires pour déplacer tous les fichiers et/ou dossiers sélectionnés." -#: templates/admin/filer/folder/choose_move_destination.html:18 +#: templates/admin/filer/folder/choose_move_destination.html:47 msgid "There are no files and/or folders available to move." -msgstr "Il n'y a pas de fichiers et/ou de dossiers disponibles à déplacer." +msgstr "Il n'y a pas de fichiers et/ou dossiers disponibles à déplacer." -#: templates/admin/filer/folder/choose_move_destination.html:20 +#: templates/admin/filer/folder/choose_move_destination.html:52 msgid "" "The following files and/or folders will be moved to a destination folder " "(retaining their tree structure):" -msgstr "" -"Les fichiers et/ou dossiers suivants seront déplacés vers un dossier de " -"destination (en conservant leur arborescence) :" +msgstr "Les fichiers et/ou dossiers suivants seront déplacés vers un dossier de destination (en conservant leur arborescence) :" -#: templates/admin/filer/folder/choose_move_destination.html:38 +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 msgid "Move" msgstr "Déplacer" -#: templates/admin/filer/folder/choose_rename_format.html:12 +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "Il est impossible de déplacer des fichiers dans le même dossier" + +#: templates/admin/filer/folder/choose_rename_format.html:15 msgid "" "Your account doesn't have permissions to rename all of the selected files." -msgstr "" -"Votre compte n'a pas les permissions nécessaires pour renommer tous les " -"fichiers sélectionnés." +msgstr "Votre compte n'a pas les permissions nécessaires pour renommer tous les fichiers sélectionnés." -#: templates/admin/filer/folder/choose_rename_format.html:15 +#: templates/admin/filer/folder/choose_rename_format.html:18 msgid "There are no files available to rename." msgstr "Il n'y a pas de fichiers disponibles à renommer." -#: templates/admin/filer/folder/choose_rename_format.html:17 +#: templates/admin/filer/folder/choose_rename_format.html:20 msgid "" "The following files will be renamed (they will stay in their folders and " "keep original filename, only displayed filename will be changed):" -msgstr "" -"Les fichiers suivants seront renommés (ils resteront dans leurs dossiers et " -"conserveront leur nom de fichier d'origine ; seul le nom affiché sera " -"changé) :" +msgstr "Les fichiers suivants seront renommés (ils resteront dans leurs dossiers et conserveront leur nom de fichier d'origine ; seul le nom affiché sera changé) :" -#: templates/admin/filer/folder/choose_rename_format.html:54 +#: templates/admin/filer/folder/choose_rename_format.html:59 msgid "Rename" msgstr "Renommer" -#: templates/admin/filer/folder/directory_listing.html:66 -msgid "Adds a new Folder" -msgstr "Ajoute un nouveau Dossier" +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "Retourner au dossier parent" -#: templates/admin/filer/folder/directory_listing.html:66 -#: templates/image_filer/include/export_dialog.html:34 -msgid "New Folder" -msgstr "Nouveau Dossier" +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "Modifier les détails du dossier actuel" -#: templates/admin/filer/folder/directory_listing.html:67 -msgid "upload files" -msgstr "transférer des fichiers" +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "Modifier" -#: templates/admin/filer/folder/directory_listing.html:67 -msgid "Upload" -msgstr "Transférer" +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "Cliquez ici pour lancer la recherche pour la phrase saisie" -#: templates/admin/filer/folder/directory_listing.html:74 -msgid "Go back to the parent folder" -msgstr "Retourner au dossier parent" +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "Rechercher" -#: templates/admin/filer/folder/directory_listing.html:76 -#: templates/admin/filer/folder/directory_table.html:29 -#: templates/admin/filer/tools/search_form.html:18 -#, python-format -msgid "1 folder" -msgid_plural "%(counter)s folders" -msgstr[0] "1 dossier" -msgstr[1] "%(counter)s dossiers" +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "Fermer" -#: templates/admin/filer/folder/directory_listing.html:76 -#: templates/admin/filer/folder/directory_table.html:29 -#: templates/admin/filer/tools/search_form.html:19 -#, python-format -msgid "1 file" -msgid_plural "%(counter)s files" -msgstr[0] "1 fichier" -msgstr[1] "%(counter)s fichiers" +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "Limite" -#: templates/admin/filer/folder/directory_listing.html:80 -msgid "Change current folder details" -msgstr "Modifie les détails du dossier courant" +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "Cochez pour limiter la recherche au dossier actuel" -#: templates/admin/filer/folder/directory_listing.html:80 -#: templates/admin/filer/folder/directory_table.html:27 -#: templates/admin/filer/folder/directory_table.html:43 -msgid "Change" -msgstr "Modifier" +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "Limiter la recherche au dossier actuel" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "Supprimer" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "Ajoute un nouveau dossier" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "Nouveau dossier" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "Téléverser des fichiers" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "Vous devez d'abord sélectionner un dossier" -#: templates/admin/filer/folder/directory_table.html:13 +#: templates/admin/filer/folder/directory_table_list.html:16 msgid "Name" msgstr "Nom" -#: templates/admin/filer/folder/directory_table.html:23 -#: templates/admin/filer/folder/directory_table.html:27 -#: templates/admin/filer/folder/directory_table.html:29 +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "Propriétaire" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "Taille" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "Action" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 #, python-format msgid "Change '%(item_label)s' folder details" msgstr "Modifier les détails du dossier « %(item_label)s »" -#: templates/admin/filer/folder/directory_table.html:30 -#: templates/admin/filer/folder/directory_table.html:45 -msgid "Owner" -msgstr "Propriétaire" +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "%(counter)s folder" +msgstr[1] "%(counter)s folders" +msgstr[2] "%(counter)s folders" -#: templates/admin/filer/folder/directory_table.html:37 +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "%(counter)s fichier" +msgstr[1] "%(counter)s fichiers" +msgstr[2] "%(counter)s fichiers" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "Changer les détails du dossier" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "Supprimer le dossier" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 msgid "Select this file" msgstr "Sélectionner ce fichier" -#: templates/admin/filer/folder/directory_table.html:39 -#: templates/admin/filer/folder/directory_table.html:43 -#: templates/admin/filer/folder/directory_table.html:44 +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 #, python-format msgid "Change '%(item_label)s' details" msgstr "Change les détails de « %(item_label)s »" -#: templates/admin/filer/folder/directory_table.html:42 -#, python-format -msgid "Delete '%(item_label)s'" -msgstr "Supprimer « %(item_label)s »" - -#: templates/admin/filer/folder/directory_table.html:42 -msgid "Delete" -msgstr "Supprimer" - -#: templates/admin/filer/folder/directory_table.html:46 +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 msgid "Permissions" msgstr "Permissions" -#: templates/admin/filer/folder/directory_table.html:46 +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 msgid "disabled" msgstr "désactivé" -#: templates/admin/filer/folder/directory_table.html:46 +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 msgid "enabled" msgstr "activé" -#: templates/admin/filer/folder/directory_table.html:50 -msgid "Move to clipboard" -msgstr "Déplacer vers le presse-papiers" +#: templates/admin/filer/folder/directory_table_list.html:144 +#| msgid "Move selected files to clipboard" +msgid "URL copied to clipboard" +msgstr "L'URL a été copiée dans le presse-papier" -#: templates/admin/filer/folder/directory_table.html:58 -msgid "there are no files or subfolders" -msgstr "il n'y a pas de fichiers ou de sous-dossiers" +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +#| msgid "Change '%(item_label)s' details" +msgid "Canonical url '%(item_label)s'" +msgstr "url canonique '%(item_label)s' " -#: templates/admin/filer/folder/directory_table.html:65 +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +#| msgid "Change '%(item_label)s' details" +msgid "Download '%(item_label)s'" +msgstr "Télécharger '%(item_label)s' " + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "Supprimer le fichier" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "Déposez des fichiers ici ou utilisez le bouton « Téléverser des fichiers »" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "Déposez votre fichier à téléverser dans :" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "Téléverser" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "annuler" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "Téléversement réussi !" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "Téléversement annulé !" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 msgid "previous" msgstr "précédent" -#: templates/admin/filer/folder/directory_table.html:69 +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 #, python-format -msgid "" -"\n" -" Page %(number)s of %(num_pages)s.\n" -" " -msgstr "" -"\n" -" Page %(number)s de %(num_pages)s.\n" -" " +msgid "Page %(number)s of %(num_pages)s." +msgstr "Page %(number)s sur %(num_pages)s." -#: templates/admin/filer/folder/directory_table.html:75 +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 msgid "next" msgstr "suivant" +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "Sélectionner les %(total_count)s" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +#| msgid "Select this file" +msgid "Select all" +msgstr "Tout sélectionner" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +#| msgid "Filer" +msgid "Files" +msgstr "Fichiers" + #: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 msgid "Add new" -msgstr "Ajouter nouveau" +msgstr "Ajouter un nouveau" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "Django site admin" -#: templates/admin/filer/folder/new_folder_form.html:13 +#: templates/admin/filer/folder/new_folder_form.html:15 msgid "Please correct the error below." msgid_plural "Please correct the errors below." msgstr[0] "Veuillez corriger l'erreur suivante." msgstr[1] "Veuillez corriger les erreurs suivantes." +msgstr[2] "Veuillez corriger les erreurs suivantes." -#: templates/admin/filer/folder/new_folder_form.html:28 +#: templates/admin/filer/folder/new_folder_form.html:30 msgid "Save" msgstr "Sauvegarder" -#: templates/admin/filer/image/change_form.html:21 -msgid "Full size preview" -msgstr "Afficher en pleine taille" +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "Votre navigateur ne supporte pas l'audio." -#: templates/admin/filer/tools/search_form.html:8 -#: templates/admin/filer/tools/search_form.html:14 -msgid "Search" -msgstr "Rechercher" +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "Votre navigateur ne supporte pas la vidéo." + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "Presse-papiers" -#: templates/admin/filer/tools/search_form.html:13 -msgid "Enter your search phrase here" -msgstr "Entrez votre phrase de recherche ici" +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "Coller tous les éléments ici" -#: templates/admin/filer/tools/search_form.html:14 -msgid "Click here to" -msgstr "Cliquez ici pour" +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "Déplacer tous les fichiers du presse-papiers vers" -#: templates/admin/filer/tools/search_form.html:14 -msgid "run search for entered phrase" -msgstr "lancer votre recherche" +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "Vider le presse-papiers" -#: templates/admin/filer/tools/search_form.html:15 -msgid "Check it to" -msgstr "Cochez pour" +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "Le presse-papiers est vide" -#: templates/admin/filer/tools/search_form.html:15 -#: templates/admin/filer/tools/search_form.html:16 -msgid "limit the search to current folder" -msgstr "Limiter la recherche au dossier courant" +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "transfert échoué" -#: templates/admin/filer/tools/search_form.html:18 +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "Télécharger" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "Agrandir" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +#| msgid "file missing" +msgid "File is missing" +msgstr "Le fichier est manquant" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "Type" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "Taille de fichier" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "Modifié" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "Créé" + +#: templates/admin/filer/tools/search_form.html:5 msgid "found" msgstr "trouvé :" -#: templates/admin/filer/tools/search_form.html:18 +#: templates/admin/filer/tools/search_form.html:5 msgid "and" msgstr "et" -#: templates/admin/filer/tools/search_form.html:19 +#: templates/admin/filer/tools/search_form.html:7 msgid "cancel search" msgstr "annuler la recherche" -#: templates/admin/filer/tools/upload_button_js.html:24 -#: templates/admin/filer/widgets/admin_file.html:7 -#: templates/admin/filer/widgets/admin_file.html:8 -msgid "file missing" -msgstr "fichier manquant" +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "Effacer" -#: templates/admin/filer/tools/clipboard/clipboard.html:7 -msgid "Clipboard" -msgstr "Presse-papiers" +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "ou déposez votre fichier ici" -#: templates/admin/filer/tools/clipboard/clipboard.html:19 -msgid "Paste all items here" -msgstr "Coller tous les éléments ici" +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "pas de fichier sélectionné" -#: templates/admin/filer/tools/clipboard/clipboard.html:26 -msgid "discard" -msgstr "Vider" +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "Recherche" -#: templates/admin/filer/tools/clipboard/clipboard.html:26 -msgid "Move all clipboard files to" -msgstr "Déplacer tous les fichiers du presse-papiers vers" +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "Sélectionner un fichier" -#: templates/admin/filer/tools/clipboard/clipboard.html:43 -msgid "the clipboard is empty" -msgstr "Le presse-papiers est vide" +#: templates/admin/filer/widgets/admin_folder.html:16 +#| msgid "Choose File" +msgid "Choose Folder" +msgstr "Choisissez un dossier" -#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:11 -msgid "upload failed" -msgstr "transfert échoué" +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "Fichier \"{file_name}\" : Hébergement refusé par la politique de sécurité du site" -#: templates/admin/filer/widgets/admin_file.html:11 -msgid "no file selected" -msgstr "pas de fichier sélectionné" +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "Fichier \"{file_name}\" : hébergement de {file_type} refusé par la politique de sécurité du site" -#: templates/admin/filer/widgets/admin_file.html:14 -#: templates/admin/filer/widgets/admin_file.html:15 -#: templates/admin/filer/widgets/admin_folder.html:7 -#: templates/admin/filer/widgets/admin_folder.html:8 -msgid "Lookup" -msgstr "Recherche" +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "Fichier \"{file_name}\" : hébergement HTML refusé par la politique de sécurité du site" -#: templates/admin/filer/widgets/admin_file.html:17 -#: templates/admin/filer/widgets/admin_folder.html:10 -msgid "Clear" -msgstr "Effacer" +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "Fichier \"{file_name}\" : Rejeté à cause d'une potentielle vulnérabilité de cross-site scripting" -#: templates/admin/filer/widgets/admin_folder.html:5 -msgid "none selected" -msgstr "aucune sélection" +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "Fichier \"{file_name}\": le format de fichier SVG n'est pas reconnu" -#: templates/image_filer/folder.html:3 -#, python-format -msgid "Folder '%(folder_label)s' files" -msgstr "Fichiers du dossier « %(folder_label)s »" +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." -#: templates/image_filer/folder.html:6 -msgid "File name" -msgstr "Nom de fichier" +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" -#: templates/image_filer/image_export_form.html:17 -msgid "export" -msgstr "exporter" +#~ msgid "Open file" +#~ msgstr "Open file" -#: templates/image_filer/image_export_form.html:27 -msgid "download image" -msgstr "télécharger l'image" +#~ msgid "Full size preview" +#~ msgstr "Full size preview" -#: templates/image_filer/include/export_dialog.html:13 -msgid "Folder name already taken." -msgstr "Nom de dossier déjà utilisé." +#~ msgid "Add Description" +#~ msgstr "Add Description" -#: templates/image_filer/include/export_dialog.html:15 -msgid "Submit" -msgstr "Envoyer" +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" +#~ msgstr[2] "15c0f2d28d6dab1af1f6d94906beb627_pl_2" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/gl/LC_MESSAGES/django.mo b/filer/locale/gl/LC_MESSAGES/django.mo new file mode 100644 index 000000000..888daadd0 Binary files /dev/null and b/filer/locale/gl/LC_MESSAGES/django.mo differ diff --git a/filer/locale/gl/LC_MESSAGES/django.po b/filer/locale/gl/LC_MESSAGES/django.po new file mode 100644 index 000000000..57767645d --- /dev/null +++ b/filer/locale/gl/LC_MESSAGES/django.po @@ -0,0 +1,1228 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +# Pablo, 2015 +# Pablo, 2015 +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Pablo, 2015\n" +"Language-Team: Galician (http://app.transifex.com/divio/django-filer/" +"language/gl/)\n" +"Language: gl\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" + +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "" + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "Avanzado" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "%(total_count)s seleccionados" +msgstr[1] "Os %(total_count)s seleccionados" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "0 de %(cnt)s seleccionados" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "Ningunha acción seleccionada." + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "Movéronse correctamente %(count)d arquivos ao portapapeis." + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "Mover arquivos seleccionados ao portapapeis." + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "" + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "" + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "" + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "Non se poden borrar arquivos e/ou carpetas" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "Estás seguro?" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "Borrar arquivos e/ou carpetas" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "Mover alquivos e/ou carpetas" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "Mover arquivos e/ou carpetas seleccionados" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "" + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "Copiar arquivos e/ou carpetas" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "Copiar arquivos e/ou carpetas seleccionados" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "" + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "Cambiar o tamaño das imaxes" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "Cambiar o tamaño das imaxes seleccionadas" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "" + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "" + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "" + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "Formato para o cambio de nome non válido: %(error)s." + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "opción da miniatura" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "ancho" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "alto" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "recortar" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "ampliar" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "" + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "" + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "" + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "" + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "" + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "" + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "texto alternativo por defecto" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "lenda por defecto" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "" + +#: models/abstract.py:91 +msgid "image" +msgstr "imaxe" + +#: models/abstract.py:92 +msgid "images" +msgstr "imaxes" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "usuario" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "arquivos" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "portapapeis" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "portapapeis" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "arquivo" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "elemento do portapapeis" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "elementos do portapapeis" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "carpeta" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "tamaño do arquivo" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "sha1" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "ten todos os datos obrigatorios" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "nome do arquivo orixinal" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "nome" + +#: models/filemodels.py:116 +msgid "description" +msgstr "descrición" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "propietario" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "subido a" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "modificado o" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "Permisos desactivados" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "creado o" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "Carpeta" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "Carpetas" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "todos os elementos" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "só este elemento" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "este elemento e todos os fillos" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "tipo" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "grupo" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "todos" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "pode ler" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "pode editar" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "pode engadir fillos" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "permiso da carpeta" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "permisos da carpeta" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "" + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "data" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "autor" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "" + +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "" +msgstr[1] "" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "" +msgstr[1] "" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:144 +#, fuzzy +#| msgid "Move selected files to clipboard" +msgid "URL copied to clipboard" +msgstr "Mover arquivos seleccionados ao portapapeis." + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "" +msgstr[1] "" + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "atopado" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "e" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "" + +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/he/LC_MESSAGES/django.mo b/filer/locale/he/LC_MESSAGES/django.mo new file mode 100644 index 000000000..f1dc779e0 Binary files /dev/null and b/filer/locale/he/LC_MESSAGES/django.mo differ diff --git a/filer/locale/he/LC_MESSAGES/django.po b/filer/locale/he/LC_MESSAGES/django.po new file mode 100644 index 000000000..6bd35b217 --- /dev/null +++ b/filer/locale/he/LC_MESSAGES/django.po @@ -0,0 +1,1249 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Angelo Dini \n" +"Language-Team: Hebrew (http://app.transifex.com/divio/django-filer/language/" +"he/)\n" +"Language: he\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % " +"1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;\n" + +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "" + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "מתקדם" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "יש לבחור פריטים על מנת לבצע עליהם פעולות. לא בוצעו פעולות." + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "אחד נבחר" +msgstr[1] "כל ה-%(total_count)s נבחרו" +msgstr[2] "כל ה-%(total_count)s נבחרו" +msgstr[3] "כל ה-%(total_count)s נבחרו" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "0 מתוך %(cnt)s נבחרו" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "לא נבחרה פעולה." + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "הועברו בהצלחה %(count)d קבצים ללוח" + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "העבר קבצים שנבחרו ללוח" + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "בוטלו בהצלחה הרשאות עבור %(count)d קבצים." + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "אופשרו בהצלחה הרשאות עבור %(count)d קבצים." + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "אופשרו הרשאות עבור קבצים בחורים" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "בוטלו הרשאות עבור קבצים בחורים" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "נמחקו בהצלחה %(count)d קבצים ו/או תיקיות." + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "לא ניתן למחוק קבצים ו/או תיקיות" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "האם את/ה בטוח/ה?" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "מחק קבצים ו/או תיקיות" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "מחק קבצים ו/או תיקיות בחורים" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "הועברו בהצלחה %(count)d קבצים ו/או תיקיות לתיקיה '%(destination)s'." + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "העבר קבצים ו/או תיקיות" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "העבר קבצים ו/או תיקיות בחורים" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "שונו בהצלחה שמותיהם של %(count)d קבצים." + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "שנה שמות קבצים" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "הועתקו בהצלחה %(count)d קבצים ו/או תיקיות לתיקיה '%(destination)s'." + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "העתק קבצים ו/או תיקיות" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "העתק קבצים ו/או תיקיות בחורים" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "שונה בהצלחה גודלם של %(count)d תמונות." + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "שנה גודל תמונות" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "שנה גודל תמונות בחורות" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "סיומת אשר תתווסף לשמות קבצים שהועתקו." + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "על הסיומת להיות תקינה, פשוטה ובאותיות קטנות, כגון \"%(valid)s\"." + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "ערך מפתח תבנית שינוי השם \"%(key)s\". אינו חוקי." + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "תבנית שינוי שם לא תקינה: %(error)s." + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "אפשרות תמונה ממוזערת" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "רוחב" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "גובה" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "חיתוך" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "הגדל" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "עליך לבחור אפשרות תמונה ממוזערת או פרמטרי שינוי גודל." + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "מיקום נושא" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "" + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "" + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "" + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "" + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "תיקיה בשם זה כבר קיימת." + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "Filer" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "טקסט חלופי ברירת מחדל" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "כותרת ברירת מחדל" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "מיקום נושא" + +#: models/abstract.py:91 +msgid "image" +msgstr "תמונה" + +#: models/abstract.py:92 +msgid "images" +msgstr "תמונות" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "משתמש" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "קבצים" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "לוח" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "לוחות" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "קובץ" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "פריט לוח" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "פריטי לוח" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "תיקיה" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "גודל קובץ" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "sha1" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "כל המידע הנחוץ קיים" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "שם קובץ מקורי" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "שם" + +#: models/filemodels.py:116 +msgid "description" +msgstr "תיאור" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "בעלים" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "הועלה ב-" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "שונה ב-" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "הרשאות בוטלו" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "נוצר ב-" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "תיקיה" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "תיקיות" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "כל הפריטים" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "פריט זה בלבד" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "פריט זה וכל ילדיו" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "סוג" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "קבוצה" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "כל אחד" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "רשאי לקרוא" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "רשאי לערוך" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "רשאי להוסיף ילדים" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "הרשאת תיקיה" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "הרשאות תיקיה" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "" + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "תאריך צילום" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "מחבר" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "חייב תמיד לפרסם קרדיט מחבר" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "חייב תמיד לפרסם זכויות יוצרים" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "קבצים עם מטה נתונים חסרים" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "שורש" + +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "הרץ את הפעולה הבחורה" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "בצע" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "לחץ כאן כדי לבחור את האובייקטים על פני כל הדפים" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "בחר את כל ה- %(total_count)s קבצים ו/או התיקיות" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "נקה בחירה" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "חזור לדף הניהול הראשי" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "בית" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "חזור לאפליקציית Filer" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "חזור לתיקיית השורש" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "חזור לתיקיה '%(folder_name)s'" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" +"עבור מחיקת הקבצים ו/או התיקיות הבחורים יש צורך למחוק אובייקטים מקושרים, אך " +"לחשבונך אין הרשאות למחוק אובייקטים מהסוגים הבאים:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "" +"עבור מחיקת הקבצים ו/או התיקיות הבחורים יש צורך למחוק את האובייקטים המוגנים " +"הבאים:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "" +"האם את/ה בטוח/ה שברצונך למחוק את הקבצים ו/או התיקיות הבחורים? כל הפריטים " +"המקושרים יימחקו:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "היסטוריה" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "צפה בתוך האתר" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "חזור ל-" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "דף הניהול הראשי" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "צלמית תיקייה" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." +msgstr "לחשבונך אין רשות להעתיק את כל הקבצים ו/או התיקיות הבחורים." + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "אין תיקיות יעד זמינות." + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "אין קבצים ו/או תיקיות זמינים להעתקה." + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "" +"הקבצים ו/או התיקיות הבאים יועתקו לתיקיית יעד (תוך שמירה על מבנה העץ שלהם):" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "תיקיית יעד:" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "העתק" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "לחשבונך אין רשות לשנות גודלן של כל התמונות הבחורות." + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "אין תמונות זמינות לשינוי גודלן." + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "התמונות הבאות ישונה גודלן:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "בחר אפשרות תמונה ממוזערת קיימת או הזן פרמטרי שינוי גודל:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "" +"הזהרה: התמונות ישונה גודלן במקום והמקוריות יאבדו. אולי ראשית עשה/י העתק שלהם " +"כדי לשמור על המקויות." + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "שנה גודל" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." +msgstr "לחשבונך אין רשות להעביר את כל הקבצים ו/או התיקיות הבחורים." + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "אין קבצים ו/או תיקיות זמינים להעברה." + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "" +"הקבצים ו/או התיקיות הבאים יועברו לתיקיית יעד (תוך שמירה על מבנה העץ שלהם):" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "העבר" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "לחשבונך אין רשות לשנות שמם של כל הקבצים הבחורים." + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "אין קבצים זמינים לשינוי שמם." + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "" +"הקבצים הבאים ישונו שמותיהם (הם יישארו בתיקיות הנוכחיות שלהם ושמם המקורי " +"יישאר - רק שמות התצוגה שלהם ישונו):" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "שנה שם" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "חזור לתיקיה ההורה" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "שנה פרטי תיקיה נוכחית" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "שנה" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "חיפוש" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "מחק" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "מוסיף תיקיה חדשה" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "תיקיה חדשה" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "שם" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "בעלים" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "שנה פרטי תיקיה של '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "בחר קובץ זה" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "שנה פרטים של '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "הרשאות" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "מבוטל" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "מאופשר" + +#: templates/admin/filer/folder/directory_table_list.html:144 +#, fuzzy +#| msgid "Move selected files to clipboard" +msgid "URL copied to clipboard" +msgstr "העבר קבצים שנבחרו ללוח" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "העלאה" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "הקודם" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "הבא" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "הוסף חדש" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "אנא תקן/י את הטעות מטה." +msgstr[1] "אנא תקן/י את הטעויות מטה." +msgstr[2] "אנא תקן/י את הטעויות מטה." +msgstr[3] "אנא תקן/י את הטעויות מטה." + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "שמור" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "לוח" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "הדבק את כל הפריטים כאן" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "העבר את כל קבצי הלוח ל-" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "הלוח ריק" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "העלאה נכשלה" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "נמצא" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "וגם" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "בטל חיפוש" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "נקה" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "אף קובץ לא נבחר" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "חיפוש" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "" + +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" +#~ msgstr[2] "15c0f2d28d6dab1af1f6d94906beb627_pl_2" +#~ msgstr[3] "15c0f2d28d6dab1af1f6d94906beb627_pl_3" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/hr/LC_MESSAGES/django.mo b/filer/locale/hr/LC_MESSAGES/django.mo new file mode 100644 index 000000000..8a2e68474 Binary files /dev/null and b/filer/locale/hr/LC_MESSAGES/django.mo differ diff --git a/filer/locale/hr/LC_MESSAGES/django.po b/filer/locale/hr/LC_MESSAGES/django.po new file mode 100644 index 000000000..956d76841 --- /dev/null +++ b/filer/locale/hr/LC_MESSAGES/django.po @@ -0,0 +1,1265 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +# Aleks Acimovic, 2022 +# Damir , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Aleks Acimovic, 2022\n" +"Language-Team: Croatian (http://app.transifex.com/divio/django-filer/" +"language/hr/)\n" +"Language: hr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "" + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "Napredno" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" +"Stavke moraju biti odabrane kako bi se obavila akcija. Nijedna stavka nije " +"promijenjena." + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "%(total_count)s odabrana" +msgstr[1] "%(total_count)s odabrano" +msgstr[2] "Svih %(total_count)s odabrano" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "Popis direktorija za %(folder_name)s" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "0 od %(cnt)s odabrano" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "Nije izabrana akcija." + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "Uspješno premješteno %(count)d datoteka u spremnik." + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "Premjesti odabrane datoteke u spremnik" + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "Uspješno onemogućene ovlasti za %(count)d datoteka." + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "Uspješno omogućene ovlasti za %(count)d datoteka." + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "Omogući ovlasti za odabrane datoteke" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "Onemogući ovlasti za odabrane datoteke" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "Uspješno obrisano %(count)d datoteka i/ili direktorija." + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "Nije moguće obrisati datoteke i/ili direktorije" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "Jeste li sigurni?" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "Obriši datoteke i/ili direktorije" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "Obriši odabrane datoteke i/ili direktorije" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" +"Uspješno premješteno %(count)d datoteka i/ili direktorija u direktorij " +"'%(destination)s'." + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "Premjesti datoteke i/ili direktorije" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "Premjesti odabrane datoteke i/ili direktorije" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "Uspješno preimenovano %(count)d datoteka." + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "Preimenuj datoteke" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" +"Uspješno kopirano %(count)d datoteka i/ili direktorija u direktorij " +"'%(destination)s'." + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "Kopiraj datoteke i/ili direktorije" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "Kopiraj odabrane datoteke i/ili direktorije" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "Uspješno promijenjena veličina za %(count)d slika." + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "Promijeni veličinu slika" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "Promijeni veličinu odabranih slika" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "Sufiks koji će biti dodan imenima kopiranih datoteka." + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "" +"Sufiks treba biti jednostavan i upisan malim slovima poput \"%(valid)s\"." + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "Nepoznata vrijednost formata ključa za preimenovanje \"%(key)s\"." + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "Neispravan format za premenovanje: %(error)s." + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "opcija sličica" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "širina" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "visina" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "obreži" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "povećaj veličinu" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "" +"Opcija sličica ili parametri za promjenu veličine moraju biti izabrani." + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "Lokacija subjekta" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "" + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "" + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "" + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "" + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "Direktorij s ovim imenom već postoji." + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "Filer" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "predefinirani alt tekst" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "predefinirani opis slike" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "lokacija subjekta" + +#: models/abstract.py:91 +msgid "image" +msgstr "slika" + +#: models/abstract.py:92 +msgid "images" +msgstr "slike" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "korisnik" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "datoteke" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "spremnik" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "spremnici" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "datoteka" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "stavka spremnika" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "stavke spremnika" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "direktorij" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "veličina datoteke" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "sha1" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "sadrži sve obavezne podatke" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "originalno ime datoteke" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "ime" + +#: models/filemodels.py:116 +msgid "description" +msgstr "opis" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "vlasnik" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "postavljeno" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "modificirano" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "Ovlasti onemogućene" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "kerirano" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "Direktorij" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "Direktoriji" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "sve stavke" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "samo ova stavka" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "ova stavka i sva djeca" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "tip" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "grupa" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "svi" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "mogu čitati" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "mogu uređivati" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "mogu dodavati djecu" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "ovlast direktorija" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "ovlasti direktorija" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "" + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "datum nastanka" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "autor" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "zahtijeva se objavljivanje zasluga autora" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "zahtjeva se objavljivanje autorskih prava" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "datoteke s nedostajućim metapodacima" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "korijenski" + +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "Pokreni odabranu akciju" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "Idi" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "Kliknite ovdje za odabir objekata kroz sve stranice" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "Odaberite sve %(total_count)s datoteke i/ili direktorije" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "Poništi odabir" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "Povratak na početnu stranicu" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "Početna" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "Povratak na Filer aplikaciju" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "Povratak na korijenski direktorij" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "Povratak na direktorij '%(folder_name)s'" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" +"Brisanje odabranih objekata bi rezultiralo brisanjem povezanih objekata, ali " +"Vaš korisnički račun nema ovlasti za brisanje slijedećih tipova objekata:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "" +"Brisanje odabranih datoteka i/ili direktorija bi zahtijevalo brisanje " +"slijedećih zaštičenih povezanih objekata:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "" +"Jeste li sigurni kako želite obrisati odabrane datoteke i/ili direktorije? " +"Svi navedeni objekti i s njima povezane stavke biti će obrisani:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "Povijest" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "Pogledaj na stranicama" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "Idi natrag na" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "početna stranica administracije" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "Ikona direktorija" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." +msgstr "" +"Vaš korisnički račun nema ovlasti za kopiranje odabranih datoteka i/ili " +"direktorija." + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "Nema dostupnih odredišnih direktorija." + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "Nema dostupnih datoteka i/ili direktorija za kopiranje." + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "" +"Slijedeće datoteke i/ili direktoriji biti će kopirani u odredišni direktorij " +"(zadržavajući postojeću strukturu):" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "Odredišni direktorij" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "Kopiraj" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "" +"Vaš korisnički račun nema ovlasti za promjenu veličina odabranih slika." + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "Nema dostupnih slika kojima bi se promijenila veličina." + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "Slijedećim slikama biti će promijenjena veličina:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "" +"Izaberite postojeću opciju sličica ili unesite parametre za promjenu " +"veličine:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "" +"Pažnja: Slikama će biti promijenjena veličina, a originali će biti prepisani " +"sa slikama s novom veličinom. Preporuča se prvo kopirati originalne slike " +"prije promjene veličine." + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "Promjeni veličinu" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." +msgstr "" +"Vaš korisnički račun nema ovlasti za premještaj svih odabranih datoteka i/" +"ili direktorija." + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "Nema dostupnih datoteka i/ili direktorija za premještaj." + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "" +"Slijedeće datoteke i/ili direktoriji biti će premješteni u odredišni " +"direktorij (zadržavajući postojeću strukturu):" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "Premjesti" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "" +"Vaš korisnički račun nema ovlasti za preimenovanje svih odabranih datoteka." + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "Nema dostupnih datoteka i/ili direktorija za preimenovanje." + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "" +"Slijedeće datoteke če biti preimenovane (ostati će u svojim direktorijima i " +"zadržati ime datoteke, samo će prikazano ime biti promijenjeno):" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "Preimenuj" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "Vrati se u nadređeni direktorij" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "Promijeni detalje trenutnog direktorija" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "Promijeni" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "Traži" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "Obriši" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "Dodaje novi direktorij" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "Novi direktorij" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "Ime" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "Vlasnik" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "Promijeni detalje direktorija '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "Odaberi ovu datoteku" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "Promijeni detalje za '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "Ovlasti" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "onemogućeno" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "omogućeno" + +#: templates/admin/filer/folder/directory_table_list.html:144 +#, fuzzy +#| msgid "Move selected files to clipboard" +msgid "URL copied to clipboard" +msgstr "Premjesti odabrane datoteke u spremnik" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "Prebaci" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "prethodni" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "slijedeći" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "Dodaj novi" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "Molimo ispravite pogrešku ispod." +msgstr[1] "Molimo ispravite pogreške ispod." +msgstr[2] "Molimo ispravite pogreške ispod." + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "Spremi" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "Privremeni spremnik" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "Premjesti sve stavke ovdje" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "Premjesti sve datoteke iz privremenog spremnika u" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "privremeni spremnik je prazan" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "prebacivanje neuspješno" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "pronađeno" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "i" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "poništi pretraživanje" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "Isprazni" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "nema odabranih datoteka" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "Pregled" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "" + +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" +#~ msgstr[2] "15c0f2d28d6dab1af1f6d94906beb627_pl_2" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/hu/LC_MESSAGES/django.mo b/filer/locale/hu/LC_MESSAGES/django.mo new file mode 100644 index 000000000..4f949fb53 Binary files /dev/null and b/filer/locale/hu/LC_MESSAGES/django.mo differ diff --git a/filer/locale/hu/LC_MESSAGES/django.po b/filer/locale/hu/LC_MESSAGES/django.po new file mode 100644 index 000000000..80b195895 --- /dev/null +++ b/filer/locale/hu/LC_MESSAGES/django.po @@ -0,0 +1,1258 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +# Istvan Farkas , 2016-2017 +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Istvan Farkas , 2016-2017\n" +"Language-Team: Hungarian (http://app.transifex.com/divio/django-filer/" +"language/hu/)\n" +"Language: hu\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" + +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "" + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "Haladó" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "egyedi URL" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" +"Az akciók végrehajtásához egy vagy több elemet ki kell választani. Egyetlen " +"elem sem változott." + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "%(total_count)s kiválasztva" +msgstr[1] "Mind (%(total_count)s) kiválasztva" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "0 kiválasztva a %(cnt)s elemből" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "Nincs akció megadva" + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "%(count)d fájl a vágólapra mozgatva." + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "Kiválasztott fájlok vágólapra mozgatása" + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "%(count)d fájl jogosultságai kikapcsolva." + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "%(count)d fájl jogosultságai bekapcsolva." + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "Jogosultságok bekapcsolása a kiválasztott fájlokhoz" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "Jogosultságok kikapcsolása a kiválasztott fájlokhoz" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "%(count)d fájl és/vagy mappa sikeresen törölve." + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "Nem lehet a mappákat és/vagy fájlokat törölni" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "Biztos benne?" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "Fájlok és/vagy mappák törlése" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "Kiválasztott fájlok és/vagy mappák törlése" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "A kiválasztott helyen már létezik %s nevű mappa" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" +"%(count)d fájl és/vagy mappa sikeresen átmozgatva ebbe a mappába: " +"%(destination)s" + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "Fájlok és/vagy mappák mozgatása" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "Kiválasztott fájlok és/vagy mappák mozgatása" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "%(count)d fájl sikeresen átnevezve." + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "Fájlok átnevezése" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" +"%(count)d fájl és/vagy mappa sikeresen átmásolva ebbe a mappába: " +"%(destination)s" + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "Fájlok és/vagy mappák másolása" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "Kiválasztott fájlok és/vagy mappák másolása" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "%(count)d kép sikeresen átméretezve." + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "Képek átméretezése" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "Kiválasztott képek átméretezése" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "Utótag, amely a másolt fájlok nevéhez lesz hozzáadva." + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "" +"Az utótag lehetőleg egyszerű, kisbetűs fájlnév részlet legyen, például " +"\"%(valid)s\"." + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "Ismeretlen átnevezés formázási szó: \"%(key)s\" " + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "Érvénytelen átnevezési formátum: %(error)s." + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "előnézeti kép beállítás" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "szélesség" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "magasság" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "vágás" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "felméretezés" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "" +"Előnézeti kép beállítást vagy átméretezési paramétert kötelező kiválasztani." + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "Fókusz helye" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "A kép fő fókuszának a helye. Formátuma: \"x,y\"." + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "Érvénytelen fókusz formátum." + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "A fókusz helye kívül esik a képen." + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "A beírt érték: \"{subject_location}\"." + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "Már létezik ilyen nevű mappa." + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "Fájlkezelő" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "Médiatár" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "alapértelmezett alternatív szöveg" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "alapértelmezett képaláírás" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "fókusz helye" + +#: models/abstract.py:91 +msgid "image" +msgstr "kép" + +#: models/abstract.py:92 +msgid "images" +msgstr "képek" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "felhasználó" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "fájlok" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "vágólap" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "vágólapok" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "fájl" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "vágólap elem" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "vágólap elemek" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "mappa" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "fájlméret" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "sha1" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "fontos adatok kitöltve" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "eredeti fájlnév" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "név" + +#: models/filemodels.py:116 +msgid "description" +msgstr "leírás" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "tulajdonos" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "feltöltés ideje" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "módosítás ideje" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "Jogosultságok kikapcsolva" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" +"Jogosultságok ellenőrzésének kikapcsolása ennél a fájlnál. Ezt a fájlt bárki " +"letöltheti." + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "létrehozás ideje" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "Mappa" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "Mappák" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "minden elem" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "csak ez az elem" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "csak ez az elem, és az alá tartozók" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "engedélyez" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "letilt" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "típus" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "csoport" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "mindenki" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "olvashatja" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "szerkesztheti" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "hozzáadhat gyermekelemet" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "mappa jogosultság" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "mappa jogosultságok" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "" + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "fotózás dátuma" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "szerző" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "szerző nevének mindig meg kell jelennie" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "copyright információnak mindig meg kell jelennie" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "szélesség pixelben." + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "magasság pixelben." + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "előnézeti kép beállítások" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "Kategorizálatlan feltöltések" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "fájlok hiányzó meta adatokkal" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "gyökér" + +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "Kiválasztott akció végrehajtása" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "Mehet" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "Ide klikkelve több oldalról is választhatóak elemek" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "Az összes (%(total_count)s) mappa és fájl kiválasztása" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "Kiválasztás megszüntetése" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "Vissza az adminisztrációs oldalra" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "Nyitólap" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "Vissza a fájlkezelőbe" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "Vissza a gyökérmappába" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "Vissza a(z) '%(folder_name)s' mappába" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "Duplikátumok" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" +"A kiválasztott fájlok és mappák törlése csatlakozó elemek törlésével is " +"járna, viszont a jelenlegi fiók nem rendelkezik a megfelelő jogosultságokkal " +"a következő objektum típusok törléséhez:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "" +"A kiválasztott fájlok és mappák törlése azzal járna, hogy a következő " +"kapcsolt elemek is törlődnek:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "" +"Biztosan törli a kiválasztott fájlokat és/vagy mappákat? A következő " +"objektumok, és a hozzájuk kapcsolt elemek is törlődni fognak:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "Nem, mégsem" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "Igen, biztos vagyok benne" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "Történet" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "Megtekintés az oldalon" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "Vissza ide:" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "adminisztrációs felület" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "Mappa Ikon" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." +msgstr "" +"Nincs jogosultsága az összes kiválasztott fájl és/vagy mappa másolásához." + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "Vissza" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "Nincs alkalmas célmappa." + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "Nincsenek másolható fájlok és/vagy könyvtárak" + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "" +"A következő fájlok és/vagy mappák lesznek a célkönyvtárba másolva (megtartva " +"a szerkezetüket):" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "Cél mappa:" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "Másol" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "Nem lehet fájlokat a saját könyvtárukba másolni" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "Nincs jogosultsága az összes kiválasztott kép átméretezéséhez." + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "Nincsenek átméretezhető képek." + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "A következő képek lesznek átméretezve:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "" +"Válasszon ki egy meglévő előnézeti kép beállítást, vagy írja be az " +"átméretezési paramétereket:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "" +"Figyelem: a képek helyben lesznek átméretezve, felülírva az eredetieket. Ha " +"meg szeretné őrizni az eredeti képeket, előbb másolja át őket." + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "Átméretezés" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." +msgstr "" +"Nincs jogosultsága az összes kiválasztott fájl és/vagy mappa mozgatásához." + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "Nincsenek mozgatható fájlok és/vagy mappák." + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "" +"A következő fájlok és/vagy mappák lesznek átmozgatva a cél mappába " +"(megtartva a szerkezetüket):" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "Mozgatás" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "Nem lehet fájlokat az eredeti mappájukba mozgatni" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "Nincs jogosultsága az összes kiválasztott fájl átnevezéséhez." + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "Nincsenek átnevezhető fájlok." + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "" +"A következő fájlok lesznek átnevezve (a mappában maradnak, és az eredeti " +"fájlnév megmarad, csak a megjelenített név változik):" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "Átnevezés" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "Vissza a szülőmappába" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "Jelenlegi mappa beállításai" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "Szerkeszt" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "Kattintson ide a beírt szó kereséséhez" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "Keresés" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "Bezár" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "Korlátozás" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "Kattintsa be, hogy a keresést a jelenlegi mappára korlátozza" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "Keresés korlátozása a jelenlegi mappára" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "Törlés" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "Új mappát hoz létre" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "Új mappa" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "Fájlok feltöltése" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "Először válasszon mappát" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "Név" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "Tulajdonos" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "Méret" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "Akció" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "A(z) '%(item_label)s' mappa beállításai" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "%(counter)s mappa" +msgstr[1] "%(counter)s mappa" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "%(counter)s fájl" +msgstr[1] "%(counter)s fájl" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "Mappa beállításainak szerkesztése" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "Mappa eltávolítása" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "Fájl kiválasztása" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "A(z) '%(item_label)s' szerkesztése" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "Jogosultságok" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "letiltva" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "engedélyezve" + +#: templates/admin/filer/folder/directory_table_list.html:144 +#, fuzzy +#| msgid "Move selected files to clipboard" +msgid "URL copied to clipboard" +msgstr "Kiválasztott fájlok vágólapra mozgatása" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "'%(item_label)s' letöltése" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "Fájl eltávolítása" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "" +"Egérrel dobjon ide fájlokat, vagy használja a \"Fájlok feltöltése\" gombot" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "Egérre dobja ide a fájl, hogy feltöltse ebbe a mappába:" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "Feltöltés" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "mégsem" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "Sikeres feltöltés!" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "Feltöltés megszakítva!" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "előző" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr " %(number)s / %(num_pages)s oldal" + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "következő" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "Összes (%(total_count)s) kiválasztása" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "Új" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "Kérjük javítsa az alábbi hibát." +msgstr[1] "Kérjük javítsa az alábbi hibákat." + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "Mentés" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "Vágólap" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "Összes elem beillesztése ide" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "Összes vágólap elem mozgatása ide: " + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "Üres vágólap" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "A vágólap üres" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "sikertelen feltöltés" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "Típus" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "Fájlméret" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "Módosítva" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "Létrehozva" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "találat" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "és " + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "keresés megszakítása" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "Törlés" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "vagy dobja ide az egérrel a fájlokat" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "nincs fájl kiválasztva" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "Keresés" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "Fájl kiválasztása" + +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/it/LC_MESSAGES/django.mo b/filer/locale/it/LC_MESSAGES/django.mo index 28289619f..b15a9a632 100644 Binary files a/filer/locale/it/LC_MESSAGES/django.mo and b/filer/locale/it/LC_MESSAGES/django.mo differ diff --git a/filer/locale/it/LC_MESSAGES/django.po b/filer/locale/it/LC_MESSAGES/django.po index 59d3aaed1..f5d95d4b7 100644 --- a/filer/locale/it/LC_MESSAGES/django.po +++ b/filer/locale/it/LC_MESSAGES/django.po @@ -3,32 +3,49 @@ # This file is distributed under the same license as the PACKAGE package. # # Translators: -# Iacopo Spalletti , 2012. -# , 2012. +# Translators: +# Translators: +# yakky , 2012 +# yakky , 2013,2015-2018 +# yakky , 2012 +# yakky , 2012-2013,2015 msgid "" msgstr "" -"Project-Id-Version: django-filer\n" +"Project-Id-Version: django Filer\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-07-13 19:10+0200\n" -"PO-Revision-Date: 2012-09-03 20:11+0100\n" -"Last-Translator: Stefan Foulis \n" -"Language-Team: Italian (http://www.transifex.com/projects/p/django-filer/" -"language/it/)\n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: yakky , 2013,2015-2018\n" +"Language-Team: Italian (http://app.transifex.com/divio/django-filer/language/" +"it/)\n" +"Language: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Language: it\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? " +"1 : 2;\n" -#: views.py:103 -msgid "Folder with this name already exists." -msgstr "Esiste già una cartella con questo nome." +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "" -#: admin/fileadmin.py:41 +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 msgid "Advanced" msgstr "Avanzato" -#: admin/folderadmin.py:324 admin/folderadmin.py:427 +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "URL standard" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 msgid "" "Items must be selected in order to perform actions on them. No items have " "been changed." @@ -36,470 +53,588 @@ msgstr "" "Gli elementi devono essere selezionati in modo da eseguire azioni su di " "essi. Nessun elemento è stato modificato." -#: admin/folderadmin.py:344 +#: admin/folderadmin.py:434 #, python-format msgid "%(total_count)s selected" msgid_plural "All %(total_count)s selected" -msgstr[0] " %(total_count)s selezionati" -msgstr[1] "Tutti %(total_count)s selezionato" +msgstr[0] " %(total_count)s elemento selezionato" +msgstr[1] "Tutti e %(total_count)s selezionati" +msgstr[2] "Tutti e %(total_count)s selezionati" -#: admin/folderadmin.py:377 +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "%(folder_name)sLista file per " + +#: admin/folderadmin.py:475 #, python-format msgid "0 of %(cnt)s selected" msgstr "0 su %(cnt)s selezionati" -#: admin/folderadmin.py:456 +#: admin/folderadmin.py:612 msgid "No action selected." msgstr "Nessuna azione selezionata." -#: admin/folderadmin.py:497 +#: admin/folderadmin.py:664 #, python-format msgid "Successfully moved %(count)d files to clipboard." msgstr "%(count)d file spostati con successo negli appunti." -#: admin/folderadmin.py:503 +#: admin/folderadmin.py:669 msgid "Move selected files to clipboard" msgstr "Sposta i file selezionati negli Appunti" -#: admin/folderadmin.py:537 +#: admin/folderadmin.py:709 #, python-format msgid "Successfully disabled permissions for %(count)d files." msgstr "Permessi per %(count)d file disabilitati con successo." -#: admin/folderadmin.py:541 +#: admin/folderadmin.py:711 #, python-format msgid "Successfully enabled permissions for %(count)d files." msgstr "Permessi per %(count)d file abilitati con successo." -#: admin/folderadmin.py:550 +#: admin/folderadmin.py:719 msgid "Enable permissions for selected files" msgstr "Attiva i permessi per i file selezionati" -#: admin/folderadmin.py:555 +#: admin/folderadmin.py:725 msgid "Disable permissions for selected files" msgstr "Disabilita i permessi per i file selezionati" -#: admin/folderadmin.py:623 +#: admin/folderadmin.py:789 #, python-format msgid "Successfully deleted %(count)d files and/or folders." msgstr "%(count)d file e/o cartelle cancellati con successo." -#: admin/folderadmin.py:630 +#: admin/folderadmin.py:794 msgid "Cannot delete files and/or folders" msgstr "Non è possibile cancellare i file e/o le cartelle" -#: admin/folderadmin.py:632 +#: admin/folderadmin.py:796 msgid "Are you sure?" msgstr "Sei sicuro?" -#: admin/folderadmin.py:637 +#: admin/folderadmin.py:802 msgid "Delete files and/or folders" msgstr "Elimina i file e/o le cartelle" -#: admin/folderadmin.py:656 +#: admin/folderadmin.py:823 msgid "Delete selected files and/or folders" msgstr "Elimina i file e/o le cartelle selezionati" -#: admin/folderadmin.py:771 +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "Esistono altre cartelle chiamate %s nella destinazione selezionata" + +#: admin/folderadmin.py:934 #, python-format msgid "" "Successfully moved %(count)d files and/or folders to folder " "'%(destination)s'." msgstr "" -"%(count)d file e/o le cartelle nella cartella '%(destination)s' spostati con " -"successo." +"%(count)d file e/o le cartelle spostati con successo nella cartella " +"'%(destination)s'." -#: admin/folderadmin.py:778 admin/folderadmin.py:780 +#: admin/folderadmin.py:942 admin/folderadmin.py:944 msgid "Move files and/or folders" -msgstr "Sposta file e/o le cartelle" +msgstr "Sposta i file e/o le cartelle" -#: admin/folderadmin.py:797 +#: admin/folderadmin.py:959 msgid "Move selected files and/or folders" msgstr "Sposta i file e/o le cartelle selezionati" -#: admin/folderadmin.py:854 +#: admin/folderadmin.py:1016 #, python-format msgid "Successfully renamed %(count)d files." msgstr "%(count)d file rinominati con successo." -#: admin/folderadmin.py:862 admin/folderadmin.py:864 admin/folderadmin.py:881 +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 msgid "Rename files" msgstr "Rinomina file" -#: admin/folderadmin.py:975 +#: admin/folderadmin.py:1137 #, python-format msgid "" "Successfully copied %(count)d files and/or folders to folder " "'%(destination)s'." msgstr "" -"%(count)d file e/o cartelle nella cartella '%(destination)s ' copiati con " -"successo." +"%(count)d file e/o cartelle copiati con successo nella cartella " +"'%(destination)s '." -#: admin/folderadmin.py:989 admin/folderadmin.py:991 +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 msgid "Copy files and/or folders" msgstr "Copia i file e/o le cartelle" -#: admin/folderadmin.py:1010 +#: admin/folderadmin.py:1174 msgid "Copy selected files and/or folders" msgstr "Copia i file e/o le cartelle selezionati" -#: admin/folderadmin.py:1105 +#: admin/folderadmin.py:1279 #, python-format msgid "Successfully resized %(count)d images." msgstr "%(count)d immagini ridimensionate con successo." -#: admin/folderadmin.py:1113 admin/folderadmin.py:1115 +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 msgid "Resize images" msgstr "Ridimensiona le immagini" -#: admin/folderadmin.py:1133 +#: admin/folderadmin.py:1303 msgid "Resize selected images" msgstr "Ridimensiona le immagini selezionate" -#: admin/forms.py:26 +#: admin/forms.py:24 msgid "Suffix which will be appended to filenames of copied files." msgstr "Suffisso che sarà aggiunto al nome dei file copiati." -#: admin/forms.py:33 +#: admin/forms.py:31 #, python-format msgid "" "Suffix should be a valid, simple and lowercase filename part, like " "\"%(valid)s\"." msgstr "" -"Il suffisso dovrebbe essere valido, semplice e minuscolo per quanto riguarda " -"la parte del nome del file, come \"%(valid)s\"." +"Il suffisso deve essere una sezione del nome del file valida, semplice e " +"minuscola, come \"%(valid)s\"." -#: admin/forms.py:54 +#: admin/forms.py:52 #, python-format msgid "Unknown rename format value key \"%(key)s\"." msgstr "Valore del formato di rinomina non valido \"%(key)s\"." -#: admin/forms.py:56 +#: admin/forms.py:54 #, python-format msgid "Invalid rename format: %(error)s." msgstr "Formato di rinomina non valido: %(error)s." -#: admin/forms.py:62 +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 msgid "thumbnail option" msgstr "opzione anteprima immagine" -#: admin/forms.py:63 +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 msgid "width" msgstr "larghezza" -#: admin/forms.py:64 +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 msgid "height" msgstr "altezza" -#: admin/forms.py:65 +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 msgid "crop" msgstr "ritaglia" -#: admin/forms.py:66 +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 msgid "upscale" msgstr "ingrandisci" -#: admin/forms.py:71 +#: admin/forms.py:79 msgid "Thumbnail option or resize parameters must be choosen." msgstr "" -"L'opzione anteprima immagine o parametri di ridimensionamento devono essere " -"selezionati." - -#: admin/forms.py:73 -msgid "Resize parameters must be choosen." -msgstr "Devono essere scelte le opzioni di ridimensionamento." +"Devi selezionare l'opzione anteprima immagine o i parametri di " +"ridimensionamento." -#: admin/imageadmin.py:12 +#: admin/imageadmin.py:20 admin/imageadmin.py:112 msgid "Subject location" msgstr "Posizione del soggetto" -#: admin/imageadmin.py:13 -msgid "Location of the main subject of the scene." -msgstr "Posizione del soggetto principale della scena." +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "Posizione del soggetto principale della scena. Formato: \"x,y\"" + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "Formato della posizione del soggetto non valida." + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "La posizione del soggetto è esterna all'immagine." + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "Valore fornito: \"{subject_location}\"" + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "Esiste già una cartella con questo nome." + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "Filer" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "Archivio file" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "testo predefinito per l'attributo alt " + +#: models/abstract.py:69 +msgid "default caption" +msgstr "didascalia predefinita" -#: models/clipboardmodels.py:9 models/foldermodels.py:236 +#: models/abstract.py:76 +msgid "subject location" +msgstr "posizione del soggetto" + +#: models/abstract.py:91 +msgid "image" +msgstr "immagine" + +#: models/abstract.py:92 +msgid "images" +msgstr "immagini" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 msgid "user" msgstr "utente" -#: models/clipboardmodels.py:11 models/filemodels.py:287 +#: models/clipboardmodels.py:17 models/filemodels.py:157 msgid "files" msgstr "file" -#: models/clipboardmodels.py:34 models/clipboardmodels.py:40 +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 msgid "clipboard" -msgstr "Appunti" +msgstr "appunti" -#: models/clipboardmodels.py:35 +#: models/clipboardmodels.py:25 msgid "clipboards" msgstr "appunti" -#: models/clipboardmodels.py:39 models/filemodels.py:35 -#: models/filemodels.py:286 +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 msgid "file" msgstr "file" -#: models/clipboardmodels.py:44 +#: models/clipboardmodels.py:56 msgid "clipboard item" -msgstr "Elemento Appunti" +msgstr "elemento degli appunti" -#: models/clipboardmodels.py:45 +#: models/clipboardmodels.py:57 msgid "clipboard items" -msgstr "Elementi Appunti" +msgstr "elementi degli appunti" -#: models/filemodels.py:33 templates/admin/filer/folder/change_form.html:9 -#: templates/admin/filer/folder/directory_listing.html:74 +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 #: templates/admin/filer/folder/new_folder_form.html:4 -#: templates/admin/filer/tools/clipboard/clipboard.html:26 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 msgid "folder" msgstr "cartella" -#: models/filemodels.py:36 +#: models/filemodels.py:81 msgid "file size" msgstr "dimensione file" -#: models/filemodels.py:38 +#: models/filemodels.py:87 msgid "sha1" msgstr "sha1" -#: models/filemodels.py:40 +#: models/filemodels.py:94 msgid "has all mandatory data" msgstr "ha tutti i dati obbligatori" -#: models/filemodels.py:42 +#: models/filemodels.py:100 msgid "original filename" msgstr "nome del file originale" -#: models/filemodels.py:44 models/foldermodels.py:99 +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 msgid "name" msgstr "nome" -#: models/filemodels.py:46 +#: models/filemodels.py:116 msgid "description" msgstr "descrizione" -#: models/filemodels.py:50 +#: models/filemodels.py:125 models/foldermodels.py:108 msgid "owner" msgstr "proprietario" -#: models/filemodels.py:52 models/foldermodels.py:105 +#: models/filemodels.py:129 models/foldermodels.py:116 msgid "uploaded at" -msgstr "caricato in " +msgstr "caricato il" -#: models/filemodels.py:53 models/foldermodels.py:108 +#: models/filemodels.py:134 models/foldermodels.py:126 msgid "modified at" -msgstr "modificato in" +msgstr "modificato il" -#: models/filemodels.py:57 +#: models/filemodels.py:140 msgid "Permissions disabled" msgstr "Permessi disabilitati" -#: models/filemodels.py:58 -msgid "Disable any permission checking for this " -msgstr "Disabilitare controllo permessi per questo" +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" +"Disabilita ogni controllo dei permessi per questo file. Il file sarà " +"accessibile da chiunque" + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "" -#: models/foldermodels.py:107 +#: models/foldermodels.py:121 msgid "created at" -msgstr "creato in" +msgstr "creato il" -#: models/foldermodels.py:211 -#: templates/admin/filer/widgets/admin_folder.html:3 -#: templates/admin/filer/widgets/admin_folder.html:5 +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 msgid "Folder" msgstr "Cartella" -#: models/foldermodels.py:212 +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 msgid "Folders" msgstr "Cartelle" -#: models/foldermodels.py:227 +#: models/foldermodels.py:260 msgid "all items" msgstr "tutti gli elementi" -#: models/foldermodels.py:228 +#: models/foldermodels.py:261 msgid "this item only" msgstr "solo questo elemento" -#: models/foldermodels.py:229 +#: models/foldermodels.py:262 msgid "this item and all children" -msgstr "questa elemento e tutti i figli" +msgstr "questo elemento e tutti i figli" -#: models/foldermodels.py:233 +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "permetti" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "nega" + +#: models/foldermodels.py:280 msgid "type" msgstr "tipo" -#: models/foldermodels.py:239 +#: models/foldermodels.py:297 msgid "group" msgstr "gruppo" -#: models/foldermodels.py:240 +#: models/foldermodels.py:304 msgid "everybody" msgstr "tutti" -#: models/foldermodels.py:242 -msgid "can edit" -msgstr "in grado modificare" - -#: models/foldermodels.py:243 +#: models/foldermodels.py:309 msgid "can read" -msgstr "in grado di leggere" +msgstr "può leggere" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "può modificare" -#: models/foldermodels.py:244 +#: models/foldermodels.py:325 msgid "can add children" -msgstr "in grado di aggiungere figli" +msgstr "può aggiungere figli" -#: models/foldermodels.py:273 +#: models/foldermodels.py:333 msgid "folder permission" msgstr "permessi cartella" -#: models/foldermodels.py:274 +#: models/foldermodels.py:334 msgid "folder permissions" msgstr "permessi cartella" -#: models/imagemodels.py:39 -msgid "date taken" -msgstr "data presa" +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" -#: models/imagemodels.py:42 -msgid "default alt text" -msgstr "testo predefinito per l'attributo alt " +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" -#: models/imagemodels.py:43 -msgid "default caption" -msgstr "didascalia predefinita" +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "" + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "" -#: models/imagemodels.py:45 templates/image_filer/image.html:6 +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "data di creazione" + +#: models/imagemodels.py:25 msgid "author" msgstr "autore" -#: models/imagemodels.py:47 +#: models/imagemodels.py:32 msgid "must always publish author credit" msgstr "pubblica sempre i crediti all'autore" -#: models/imagemodels.py:48 +#: models/imagemodels.py:37 msgid "must always publish copyright" msgstr "pubblica sempre il copyright" -#: models/imagemodels.py:50 -msgid "subject location" -msgstr "posizione del soggetto" +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "larghezza in pixel." -#: models/imagemodels.py:200 -msgid "image" -msgstr "immagine" +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "altezza in pixel." -#: models/imagemodels.py:201 -msgid "images" -msgstr "immagini" +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "opzione anteprima immagine" -#: models/virtualitems.py:45 -#: templates/admin/filer/tools/clipboard/clipboard.html:26 -msgid "unfiled files" -msgstr "file archiviati" +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "File non archiviati" -#: models/virtualitems.py:59 +#: models/virtualitems.py:73 msgid "files with missing metadata" msgstr "file con metadati mancanti" -#: models/virtualitems.py:73 templates/admin/filer/breadcrumbs.html:6 -#: templates/admin/filer/folder/change_form.html:9 -#: templates/admin/filer/folder/directory_listing.html:74 -#: templates/image_filer/image_export_form.html:10 +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 msgid "root" msgstr "cartella principale" -#: templates/admin/filer/actions.html:4 +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 msgid "Run the selected action" msgstr "Esegui l'azione selezionata" -#: templates/admin/filer/actions.html:4 +#: templates/admin/filer/actions.html:5 msgid "Go" msgstr "Vai" -#: templates/admin/filer/actions.html:11 +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 msgid "Click here to select the objects across all pages" msgstr "Clicca qui per selezionare gli oggetti in tutte le pagine" -#: templates/admin/filer/actions.html:11 +#: templates/admin/filer/actions.html:14 #, python-format msgid "Select all %(total_count)s files and/or folders" msgstr "Seleziona tutti i %(total_count)s file e/o cartelle" -#: templates/admin/filer/actions.html:13 +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 msgid "Clear selection" msgstr "Cancella selezione" #: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 msgid "Go back to admin homepage" msgstr "Torna alla pagina iniziale di admin" #: templates/admin/filer/breadcrumbs.html:4 -#: templates/admin/filer/folder/change_form.html:7 -#: templates/image_filer/image_export_form.html:7 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 msgid "Home" msgstr "Pagina iniziale" #: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 msgid "Go back to Filer app" msgstr "Torna all'app Filer" -#: templates/admin/filer/breadcrumbs.html:5 -#: templates/admin/filer/folder/change_form.html:8 -#: templates/image_filer/image_export_form.html:8 -msgid "Filer" -msgstr "Filer" - #: templates/admin/filer/breadcrumbs.html:6 -#: templates/image_filer/image_export_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:35 msgid "Go back to root folder" msgstr "Torna alla cartella principale" #: templates/admin/filer/breadcrumbs.html:8 -#: templates/admin/filer/breadcrumbs.html:11 -#: templates/admin/filer/folder/change_form.html:11 -#: templates/image_filer/image_export_form.html:12 -#: templates/image_filer/image_export_form.html:14 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 #, python-format msgid "Go back to '%(folder_name)s' folder" msgstr "Torna alla cartella ' %(folder_name)s '" -#: templates/admin/filer/change_form.html:28 -msgid "duplicates" -msgstr "duplicati" - -#: templates/admin/filer/delete_confirmation.html:13 -#, python-format -msgid "" -"Deleting the %(object_name)s '%(escaped_object)s' would result in deleting " -"related objects, but your account doesn't have permission to delete the " -"following types of objects:" -msgstr "" -"La cancellazione dell'elemento %(object_name)s '%(escaped_object)s' richiede " -"la cancellazione di elementi collegati, ma il tuo account non ha i permessi " -"per cancellare i seguenti tipi di oggetto:" - -#: templates/admin/filer/delete_confirmation.html:21 -#, python-format -msgid "" -"Deleting the %(object_name)s '%(escaped_object)s' would require deleting the " -"following protected related objects:" -msgstr "" -"La cancellazione dell'elemento %(object_name)s '%(escaped_object)s' richiede " -"la cancellazione dei seguenti elementi protetti collegati:" - -#: templates/admin/filer/delete_confirmation.html:29 -#, python-format -msgid "" -"Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? " -"All of the following related items will be deleted:" -msgstr "" -"Sei sicuro di voler cancellare l'elemento %(object_name)s " -"\"%(escaped_object)s\"? \n" -"Tutti gli elementi collegati seguenti saranno cancellati:" - -#: templates/admin/filer/delete_confirmation.html:34 -#: templates/admin/filer/delete_selected_files_confirmation.html:45 -msgid "Yes, I'm sure" -msgstr "Sì, sono sicuro" +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "Duplicati" #: templates/admin/filer/delete_selected_files_confirmation.html:11 msgid "" @@ -527,39 +662,52 @@ msgstr "" "Sei sicuro di voler cancellare i file selezionati e/o le cartelle? Tutti gli " "oggetti seguenti e quelli correlati verranno cancellati:" -#: templates/admin/filer/folder/change_form.html:7 -#: templates/admin/filer/folder/change_form.html:8 -#: templates/admin/filer/folder/change_form.html:9 -#: templates/admin/filer/folder/directory_listing.html:74 -#: templates/image_filer/image_export_form.html:7 -#: templates/image_filer/image_export_form.html:8 -#: templates/image_filer/image_export_form.html:16 -msgid "Go back to" -msgstr "Torna a" +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "No, torna indietro" -#: templates/admin/filer/folder/change_form.html:7 -#: templates/image_filer/image_export_form.html:7 -msgid "admin homepage" -msgstr "Pagina iniziale admin" +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "Sì, sono sicuro" -#: templates/admin/filer/folder/change_form.html:22 -#: templates/admin/filer/image/change_form.html:9 +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 msgid "History" msgstr "Storia" +#: templates/admin/filer/file/change_form.html:37 #: templates/admin/filer/folder/change_form.html:23 -#: templates/admin/filer/image/change_form.html:10 +#: templates/admin/filer/image/change_form.html:37 msgid "View on site" msgstr "Vedi sul sito" -#: templates/admin/filer/folder/change_form.html:35 -#: templates/admin/filer/folder/directory_listing.html:75 -#: templates/admin/filer/folder/directory_listing.html:85 -#: templates/admin/filer/folder/directory_table.html:23 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "Torna a" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "Pagina iniziale admin" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 msgid "Folder Icon" msgstr "Icona della cartella" -#: templates/admin/filer/folder/choose_copy_destination.html:12 +#: templates/admin/filer/folder/choose_copy_destination.html:23 msgid "" "Your account doesn't have permissions to copy all of the selected files and/" "or folders." @@ -567,16 +715,25 @@ msgstr "" "Il tuo account non dispone delle autorizzazioni per copiare tutti i file e/o " "cartelle selezionati." -#: templates/admin/filer/folder/choose_copy_destination.html:15 -#: templates/admin/filer/folder/choose_move_destination.html:15 +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "Torna indietro" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 msgid "There are no destination folders available." msgstr "Non ci sono cartelle di destinazione disponibili." -#: templates/admin/filer/folder/choose_copy_destination.html:18 +#: templates/admin/filer/folder/choose_copy_destination.html:35 msgid "There are no files and/or folders available to copy." msgstr "Non ci sono file e/o le cartelle disponibili per la copia." -#: templates/admin/filer/folder/choose_copy_destination.html:20 +#: templates/admin/filer/folder/choose_copy_destination.html:40 msgid "" "The following files and/or folders will be copied to a destination folder " "(retaining their tree structure):" @@ -584,41 +741,43 @@ msgstr "" "I seguenti file e/o cartelle verranno copiati in una cartella di " "destinazione (mantenendo la loro struttura ad albero):" -#: templates/admin/filer/folder/choose_copy_destination.html:32 -#: templates/admin/filer/folder/choose_move_destination.html:32 +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 msgid "Destination folder:" msgstr "Cartella di destinazione:" -#: templates/admin/filer/folder/choose_copy_destination.html:39 +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 msgid "Copy" msgstr "Copia" -#: templates/admin/filer/folder/choose_images_resize_options.html:12 +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "Non è autorizzato a copiare file nella stessa cartella" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 msgid "" "Your account doesn't have permissions to resize all of the selected images." msgstr "" "Il tuo account non dispone delle autorizzazioni per ridimensionare tutte le " "immagini selezionate." -#: templates/admin/filer/folder/choose_images_resize_options.html:15 +#: templates/admin/filer/folder/choose_images_resize_options.html:18 msgid "There are no images available to resize." msgstr "Non ci sono immagini disponibili da ridimensionare." -#: templates/admin/filer/folder/choose_images_resize_options.html:17 +#: templates/admin/filer/folder/choose_images_resize_options.html:20 msgid "The following images will be resized:" msgstr "Le seguenti immagini verranno ridimensionate:" -#: templates/admin/filer/folder/choose_images_resize_options.html:30 +#: templates/admin/filer/folder/choose_images_resize_options.html:32 msgid "Choose an existing thumbnail option or enter resize parameters:" msgstr "" -"Scegli un'opzione esistente miniatura o immettere i parametri di " +"Scegli un'opzione miniatura esistente o immetti i parametri di " "ridimensionamento:" -#: templates/admin/filer/folder/choose_images_resize_options.html:32 -msgid "Choose resize parameters:" -msgstr "Scegli i parametri di ridimensionamento:" - -#: templates/admin/filer/folder/choose_images_resize_options.html:35 +#: templates/admin/filer/folder/choose_images_resize_options.html:36 msgid "" "Warning: Images will be resized in-place and originals will be lost. Maybe " "first make a copy of them to retain the originals." @@ -626,11 +785,11 @@ msgstr "" "Attenzione: Le immagini verranno ridimensionate ora e le immagini originali " "andranno perse. Forse è meglio fare una copia per mantenere i file originali." -#: templates/admin/filer/folder/choose_images_resize_options.html:36 +#: templates/admin/filer/folder/choose_images_resize_options.html:39 msgid "Resize" msgstr "Ridimensiona" -#: templates/admin/filer/folder/choose_move_destination.html:12 +#: templates/admin/filer/folder/choose_move_destination.html:35 msgid "" "Your account doesn't have permissions to move all of the selected files and/" "or folders." @@ -638,11 +797,11 @@ msgstr "" "Il tuo account non dispone delle autorizzazioni per spostare tutti i file e/" "o cartelle selezionati." -#: templates/admin/filer/folder/choose_move_destination.html:18 +#: templates/admin/filer/folder/choose_move_destination.html:47 msgid "There are no files and/or folders available to move." msgstr "Non ci sono file e/o cartelle a disponibili per lo spostamento." -#: templates/admin/filer/folder/choose_move_destination.html:20 +#: templates/admin/filer/folder/choose_move_destination.html:52 msgid "" "The following files and/or folders will be moved to a destination folder " "(retaining their tree structure):" @@ -650,22 +809,28 @@ msgstr "" "I seguenti file e/o cartelle verranno spostati in una cartella di " "destinazione (mantenendo la loro struttura ad albero):" -#: templates/admin/filer/folder/choose_move_destination.html:38 +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 msgid "Move" msgstr "Sposta" -#: templates/admin/filer/folder/choose_rename_format.html:12 +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "Non è autorizzato a spostare file nella stessa cartella" + +#: templates/admin/filer/folder/choose_rename_format.html:15 msgid "" "Your account doesn't have permissions to rename all of the selected files." msgstr "" "Il tuo account non dispone delle autorizzazioni per rinominare tutti i file " "selezionati." -#: templates/admin/filer/folder/choose_rename_format.html:15 +#: templates/admin/filer/folder/choose_rename_format.html:18 msgid "There are no files available to rename." -msgstr "Non ci sono file disponibili da ridimensionare." +msgstr "Non ci sono file disponibili da rinominare." -#: templates/admin/filer/folder/choose_rename_format.html:17 +#: templates/admin/filer/folder/choose_rename_format.html:20 msgid "" "The following files will be renamed (they will stay in their folders and " "keep original filename, only displayed filename will be changed):" @@ -674,260 +839,436 @@ msgstr "" "manterranno il nome del file originario, solo il nome visualizzato sarà " "modificato):" -#: templates/admin/filer/folder/choose_rename_format.html:54 +#: templates/admin/filer/folder/choose_rename_format.html:59 msgid "Rename" msgstr "Rinomina" -#: templates/admin/filer/folder/directory_listing.html:66 -msgid "Adds a new Folder" -msgstr "Aggiungi una nuova cartella" +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "Torna alla cartella superiore" -#: templates/admin/filer/folder/directory_listing.html:66 -#: templates/image_filer/include/export_dialog.html:34 -msgid "New Folder" -msgstr "Nuova cartella" +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "Modifica i dettagli della cartella corrente" -#: templates/admin/filer/folder/directory_listing.html:67 -msgid "upload files" -msgstr "carica file" +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "Modifica" -#: templates/admin/filer/folder/directory_listing.html:67 -msgid "Upload" -msgstr "Carica" +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "Clicca qui per eseguire la ricerca della frase inserita" -#: templates/admin/filer/folder/directory_listing.html:74 -msgid "Go back to the parent folder" -msgstr "Torna alla cartella superiore" +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "Cerca" -#: templates/admin/filer/folder/directory_listing.html:76 -#: templates/admin/filer/folder/directory_table.html:29 -#: templates/admin/filer/tools/search_form.html:18 -#, python-format -msgid "1 folder" -msgid_plural "%(counter)s folders" -msgstr[0] "1 cartella" -msgstr[1] "%(counter)s cartelle" +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "Chiudi" -#: templates/admin/filer/folder/directory_listing.html:76 -#: templates/admin/filer/folder/directory_table.html:29 -#: templates/admin/filer/tools/search_form.html:19 -#, python-format -msgid "1 file" -msgid_plural "%(counter)s files" -msgstr[0] "1 file" -msgstr[1] "%(counter)s file" +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "Limita" -#: templates/admin/filer/folder/directory_listing.html:80 -msgid "Change current folder details" -msgstr "Modifica dettagli cartella corrente" +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "Seleziona per limitare la ricerca alla cartella corrente" -#: templates/admin/filer/folder/directory_listing.html:80 -#: templates/admin/filer/folder/directory_table.html:27 -#: templates/admin/filer/folder/directory_table.html:43 -msgid "Change" -msgstr "Cambia" +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "Limita la ricerca alla cartella corrente" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "Cancella" -#: templates/admin/filer/folder/directory_table.html:13 +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "Aggiungi una nuova cartella" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "Nuova cartella" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "Carica file" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "E' necessario selezionare prima una cartella" + +#: templates/admin/filer/folder/directory_table_list.html:16 msgid "Name" msgstr "Nome" -#: templates/admin/filer/folder/directory_table.html:23 -#: templates/admin/filer/folder/directory_table.html:27 -#: templates/admin/filer/folder/directory_table.html:29 +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "Proprietario" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "Dimensione" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "Azione" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 #, python-format msgid "Change '%(item_label)s' folder details" -msgstr "Modifica dettagli cartella '%(item_label)s'" +msgstr "Modifica i dettagli della cartella '%(item_label)s'" -#: templates/admin/filer/folder/directory_table.html:30 -#: templates/admin/filer/folder/directory_table.html:45 -msgid "Owner" -msgstr "Proprietario" +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "%(counter)s cartella" +msgstr[1] "%(counter)s cartelle" +msgstr[2] "%(counter)s cartelle" -#: templates/admin/filer/folder/directory_table.html:37 +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "%(counter)s file" +msgstr[1] "%(counter)s file" +msgstr[2] "%(counter)s file" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "Modifica i dettagli della cartella" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "Cancella cartella" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 msgid "Select this file" msgstr "Seleziona questo file" -#: templates/admin/filer/folder/directory_table.html:39 -#: templates/admin/filer/folder/directory_table.html:43 -#: templates/admin/filer/folder/directory_table.html:44 +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 #, python-format msgid "Change '%(item_label)s' details" -msgstr "Cambia dettagli ' %(item_label)s ' " +msgstr "Modifica i dettagli di ' %(item_label)s ' " -#: templates/admin/filer/folder/directory_table.html:42 -#, python-format -msgid "Delete '%(item_label)s'" -msgstr "Cancella '%(item_label)s'" - -#: templates/admin/filer/folder/directory_table.html:42 -msgid "Delete" -msgstr "Cancella" - -#: templates/admin/filer/folder/directory_table.html:46 +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 msgid "Permissions" msgstr "Permessi" -#: templates/admin/filer/folder/directory_table.html:46 +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 msgid "disabled" msgstr "disabilitato" -#: templates/admin/filer/folder/directory_table.html:46 +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 msgid "enabled" msgstr "abilitato" -#: templates/admin/filer/folder/directory_table.html:50 -msgid "Move to clipboard" -msgstr "Sposta negli Appunti" +#: templates/admin/filer/folder/directory_table_list.html:144 +#, fuzzy +#| msgid "Move selected files to clipboard" +msgid "URL copied to clipboard" +msgstr "Sposta i file selezionati negli Appunti" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "URL canonico '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "Download '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "Cancella file" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "Posiziona qui i file o usa il bottone \"Carica file\"" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "Posiziona il file da caricare in:" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "Carica" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "annulla" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "Caricamento avvenuto!" -#: templates/admin/filer/folder/directory_table.html:58 -msgid "there are no files or subfolders" -msgstr "non ci sono file o sottocartelle" +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "Caricamento annullato!" -#: templates/admin/filer/folder/directory_table.html:65 +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 msgid "previous" msgstr "precedente" -#: templates/admin/filer/folder/directory_table.html:69 +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 #, python-format -msgid "" -"\n" -" Page %(number)s of %(num_pages)s.\n" -" " -msgstr "" -"\n" -"Pagina %(number)s su %(num_pages)s ." +msgid "Page %(number)s of %(num_pages)s." +msgstr "Pagina %(number)s su %(num_pages)s." -#: templates/admin/filer/folder/directory_table.html:75 +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 msgid "next" msgstr "prossima" +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "Seleziona tutti %(total_count)s" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "" + #: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 msgid "Add new" -msgstr "Aggiungi nuova" +msgstr "Aggiungi nuovo" -#: templates/admin/filer/folder/new_folder_form.html:13 +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "Amministrazione Django" + +#: templates/admin/filer/folder/new_folder_form.html:15 msgid "Please correct the error below." msgid_plural "Please correct the errors below." msgstr[0] "Correggi l'errore qui sotto." msgstr[1] "Correggi gli errori qui sotto." +msgstr[2] "Correggi gli errori qui sotto." -#: templates/admin/filer/folder/new_folder_form.html:28 +#: templates/admin/filer/folder/new_folder_form.html:30 msgid "Save" msgstr "Salva" -#: templates/admin/filer/image/change_form.html:21 -msgid "Full size preview" -msgstr "Anteprima a tutto schermo" +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" -#: templates/admin/filer/tools/search_form.html:8 -#: templates/admin/filer/tools/search_form.html:14 -msgid "Search" -msgstr "Cerca" +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" -#: templates/admin/filer/tools/search_form.html:13 -msgid "Enter your search phrase here" -msgstr "Inserisci la tua frase di ricerca qui" +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "Appunti" -#: templates/admin/filer/tools/search_form.html:14 -msgid "Click here to" -msgstr "Clicca qui per" +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "Incolla qui tutti gli elementi" -#: templates/admin/filer/tools/search_form.html:14 -msgid "run search for entered phrase" -msgstr "esegui la ricerca per frase inserita" +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "Sposta tutti i file negli Appunti in" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "Svuota appunti" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "gli appunti sono vuoti" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "caricamento fallito" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" -#: templates/admin/filer/tools/search_form.html:15 -msgid "Check it to" -msgstr "Seleziona per" +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "Tipo" -#: templates/admin/filer/tools/search_form.html:15 -#: templates/admin/filer/tools/search_form.html:16 -msgid "limit the search to current folder" -msgstr "limitare la ricerca alla cartella corrente" +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "Dimensione file" -#: templates/admin/filer/tools/search_form.html:18 +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "Modificato" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "Creato" + +#: templates/admin/filer/tools/search_form.html:5 msgid "found" msgstr "trovato" -#: templates/admin/filer/tools/search_form.html:18 +#: templates/admin/filer/tools/search_form.html:5 msgid "and" msgstr "e" -#: templates/admin/filer/tools/search_form.html:19 +#: templates/admin/filer/tools/search_form.html:7 msgid "cancel search" msgstr "annulla ricerca" -#: templates/admin/filer/tools/upload_button_js.html:24 -#: templates/admin/filer/widgets/admin_file.html:7 -#: templates/admin/filer/widgets/admin_file.html:8 -msgid "file missing" -msgstr "file mancante" +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "Cancella" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "o posiziona il file qui" -#: templates/admin/filer/tools/clipboard/clipboard.html:7 -msgid "Clipboard" -msgstr "Appunti" +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "nessun file selezionato" -#: templates/admin/filer/tools/clipboard/clipboard.html:19 -msgid "Paste all items here" -msgstr "Incolla qui tutti gli elementi" +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "Consultazione" -#: templates/admin/filer/tools/clipboard/clipboard.html:26 -msgid "discard" -msgstr "annulla" +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "Seleziona file" -#: templates/admin/filer/tools/clipboard/clipboard.html:26 -msgid "Move all clipboard files to" -msgstr "Sposta tutti i file negli Appunti in" +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" -#: templates/admin/filer/tools/clipboard/clipboard.html:43 -msgid "the clipboard is empty" -msgstr "gli Appunti sono vuoti" +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" -#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:11 -msgid "upload failed" -msgstr "caricamento fallito" +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" -#: templates/admin/filer/widgets/admin_file.html:11 -msgid "no file selected" -msgstr "nessun file selezionato" +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" -#: templates/admin/filer/widgets/admin_file.html:14 -#: templates/admin/filer/widgets/admin_file.html:15 -#: templates/admin/filer/widgets/admin_folder.html:7 -#: templates/admin/filer/widgets/admin_folder.html:8 -msgid "Lookup" -msgstr "Consultazione" +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" -#: templates/admin/filer/widgets/admin_file.html:17 -#: templates/admin/filer/widgets/admin_folder.html:10 -msgid "Clear" -msgstr "Cancella" +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "" -#: templates/admin/filer/widgets/admin_folder.html:5 -msgid "none selected" -msgstr "nessun elemento selezionato" +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." -#: templates/image_filer/folder.html:3 -#, python-format -msgid "Folder '%(folder_label)s' files" -msgstr "File cartella ' %(folder_label)s '" +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" -#: templates/image_filer/folder.html:6 -msgid "File name" -msgstr "Nome file" +#~ msgid "none selected" +#~ msgstr "none selected" -#: templates/image_filer/image_export_form.html:17 -msgid "export" -msgstr "esporta" +#~ msgid "Add Folder" +#~ msgstr "Add Folder" -#: templates/image_filer/image_export_form.html:27 -msgid "download image" -msgstr "scarica immagine" +#~ msgid "Subject Location" +#~ msgstr "Subject location" -#: templates/image_filer/include/export_dialog.html:13 -msgid "Folder name already taken." -msgstr "Nome cartella già utilizzato." +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" +#~ msgstr[2] "15c0f2d28d6dab1af1f6d94906beb627_pl_2" -#: templates/image_filer/include/export_dialog.html:15 -msgid "Submit" -msgstr "Invia" +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/ja/LC_MESSAGES/django.mo b/filer/locale/ja/LC_MESSAGES/django.mo new file mode 100644 index 000000000..f18d8161c Binary files /dev/null and b/filer/locale/ja/LC_MESSAGES/django.mo differ diff --git a/filer/locale/ja/LC_MESSAGES/django.po b/filer/locale/ja/LC_MESSAGES/django.po new file mode 100644 index 000000000..bb438c591 --- /dev/null +++ b/filer/locale/ja/LC_MESSAGES/django.po @@ -0,0 +1,1219 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Angelo Dini \n" +"Language-Team: Japanese (http://app.transifex.com/divio/django-filer/" +"language/ja/)\n" +"Language: ja\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "" + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "" + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "" + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "" + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "" + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "" + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "" + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "" + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "" + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "" + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "" + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "" + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "" + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "" + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "" + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "" + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "" + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "" + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "" + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "" + +#: models/abstract.py:91 +msgid "image" +msgstr "" + +#: models/abstract.py:92 +msgid "images" +msgstr "" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "" + +#: models/filemodels.py:116 +msgid "description" +msgstr "" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "" + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "" + +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:144 +msgid "URL copied to clipboard" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "" + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "" + +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/ja_JP/LC_MESSAGES/django.mo b/filer/locale/ja_JP/LC_MESSAGES/django.mo new file mode 100644 index 000000000..c1581e2b2 Binary files /dev/null and b/filer/locale/ja_JP/LC_MESSAGES/django.mo differ diff --git a/filer/locale/ja_JP/LC_MESSAGES/django.po b/filer/locale/ja_JP/LC_MESSAGES/django.po new file mode 100644 index 000000000..72b1160c9 --- /dev/null +++ b/filer/locale/ja_JP/LC_MESSAGES/django.po @@ -0,0 +1,1219 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Angelo Dini \n" +"Language-Team: Japanese (Japan) (http://app.transifex.com/divio/django-filer/" +"language/ja_JP/)\n" +"Language: ja_JP\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "" + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "" + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "" + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "" + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "" + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "" + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "" + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "" + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "" + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "" + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "" + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "" + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "" + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "" + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "" + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "" + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "" + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "" + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "" + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "" + +#: models/abstract.py:91 +msgid "image" +msgstr "" + +#: models/abstract.py:92 +msgid "images" +msgstr "" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "" + +#: models/filemodels.py:116 +msgid "description" +msgstr "" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "" + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "" + +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:144 +msgid "URL copied to clipboard" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "" + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "" + +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/lt/LC_MESSAGES/django.mo b/filer/locale/lt/LC_MESSAGES/django.mo new file mode 100644 index 000000000..de0708e70 Binary files /dev/null and b/filer/locale/lt/LC_MESSAGES/django.mo differ diff --git a/filer/locale/lt/LC_MESSAGES/django.po b/filer/locale/lt/LC_MESSAGES/django.po new file mode 100644 index 000000000..fdd11fd6a --- /dev/null +++ b/filer/locale/lt/LC_MESSAGES/django.po @@ -0,0 +1,1273 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +# Matas Dailyda , 2015-2018 +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Matas Dailyda , 2015-2018\n" +"Language-Team: Lithuanian (http://app.transifex.com/divio/django-filer/" +"language/lt/)\n" +"Language: lt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < " +"11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? " +"1 : n % 1 != 0 ? 2: 3);\n" + +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "" + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "Išplėstinės funkcijos" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "kanoninis URL" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" +"Objektai turi būti pasirinkti, kad su jais būtų galima atlikti veiksmus. " +"Jokie objektai nebuvo pakeisti." + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "pasirinkta %(total_count)s" +msgstr[1] "pasirinkta %(total_count)s" +msgstr[2] "pasirinkta %(total_count)s" +msgstr[3] "pasirinkta %(total_count)s" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "%(folder_name)svidinių aplankų sąrašas " + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "0 iš %(cnt)s pasirinkta" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "Nepasirinktas joks veiksmas." + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "Sėkmingai perkelta %(count)d failai į iškarpinę." + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "Perkelti pažymėtus failus į iškarpinę" + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "Sėkmingai išjungti leidimai %(count)d failams." + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "Sėkmingai įjungti leidimai %(count)d failams." + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "Įjungti leidimus pasirinktiems failams" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "Išjungti leidimus pasirinktiems failams" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "Sėkmingai pašalino %(count)d failus ir / ar aplankus." + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "Negalima pašalinti failų ir / ar aplankų" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "Ar jūs esate tikri?" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "Pašalinti failus ir / ar aplankus" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "Pašalinti pasirinktus failus ir / ar aplankus" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "" +"Aplankai su %s pavadinimais jau egzistuoja pasirinktoje paskirties vietoje." + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" +"Sėkmingai perkelti %(count)d failai ir / ar aplankai į aplanką " +"'%(destination)s'." + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "Perkelti failus ir / ar aplankus" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "Perkelti pasirinktus failus ir / ar aplankus" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "Sėkmingai pervardinti %(count)d failai." + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "Pervardinti failus" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" +"Sėkmingai nukopijuoti %(count)d failai ir / ar aplankai į aplanką " +"'%(destination)s'." + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "Kopijuoti failus ir / ar aplankus" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "Kopijuoti pasirinktus failus ir / ar aplankus" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "Sėkmingai pakeistas %(count)d paveikslėlių dydis." + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "Pakeisti paveikslėlių dydžius" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "Pakeisti pasirinktų paveikslėlių dydžius" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "Priesaga kuri bus pridėta prie nukopijuotų failų pavadinimų." + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "" +"Priesaga turi būti paprasta ir taisyklinga bylos pavadinimo dalis pvz. " +"\"%(valid)s\"." + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "Nežinomas pervardinimo formato reikšmės raktažodis \"%(key)s\"." + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "Negalimas pervardinimo formatas: %(error)s." + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "miniatiūros nustatymas" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "plotis" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "aukštis" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "apkirpti" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "išdidinti" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "" +"Miniatiūros nustatymas arba dydžio keitimo parametrai turi būti pasirinkti." + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "Subjekto vieta" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "Pagrindinio subjekto vieta vaizde. Fomatas: \"x,y\"." + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "Netinkamas subjekto vietos formatas." + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "Subjekto vieta yra už paveikslėlio." + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "Jūsų įvestis: \"{subject_location}\". " + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "Aplankas su tokiu pavadinimu jau egzistuoja." + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "Filer'is" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "Medijos biblioteka" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "numatytasis alternatyvus tekstas" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "numatytoji antraštė" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "subjekto vieta" + +#: models/abstract.py:91 +msgid "image" +msgstr "paveikslėlis" + +#: models/abstract.py:92 +msgid "images" +msgstr "paveikslėliai" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "vartotojas" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "failai" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "iškarpinė" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "iškarpinės" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "failas" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "iškarpinės objektas" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "iškarpinės objektai" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "aplankas" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "failo dydis" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "sha1" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "turi visus privalomus duomenis" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "originalus failo pavadinimas" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "pavadinimas" + +#: models/filemodels.py:116 +msgid "description" +msgstr "apibūdinimas" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "savininkas" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "įkelta" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "pakeista" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "Leidimai išjungti" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" +"Įšjungti bet kokius leidimų tikrinimus šiai bylai. Byla bus viešai " +"pasiekiama bet kam." + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "sukurta" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "Aplankas" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "Aplankai" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "visi objektai" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "tik šį objektą" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "šį objektą ir visus vidinius" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "leisti" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "neleisti" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "tipas" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "grupė" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "visi" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "gali skaityti" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "gali redaguoti" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "gali pridėti vidinius" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "aplanko leidimas" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "aplanko leidimai" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "" + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "paimta data" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "autorius" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "visada turi publikuoti autorystę" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "visada turi publikuoti autorių teises" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "plotis pikseliais." + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "aukštis pikseliais." + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "miniatiūros nustatymai" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "Nerūšiuotos įkeltos bylos" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "failai su trūkstamais meta duomenimis" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "pradinis" + +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "Vykdyti pasirinktą veiksmą" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "Eiti" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "Spauskite čia kad pasirinktumete objektus per visus puslapius" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "Pasirinkti visus %(total_count)s failus ir / ar aplankus" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "Išvalyti pasirinkimus" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "Grįžti į pradinį administravimo puslapį" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "Pradinis" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "Grįžti į Failer'io apklikaciją" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "Grįžti į pradinį aplanką" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "Grįžti į '%(folder_name)s' aplanką" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "Dublikatai" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" +"Pasirintų failų ir / ar aplankų šalinimas pašalintų susijusius objektus, " +"tačiau jūsų vartotojas neturi leidimo šalinti šių objektų tipų:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "" +"Pasirinktų failų ir / ar aplankų šalinimas reikalautų pašalinti šiuos " +"apsaugotus susijusius objektus:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "" +"Ar tikrai norite pašalinti pasirinktus failus ir / ar aplankus? Visi susiję " +"objektai bus pašalinti:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "Ne, grįžti atgal" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "Taip, esu tikras" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "Istorija" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "Žiūrėti puslapyje" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "Grįžti į" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "administravimo pradinis puslapis" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "Aplanko piktograma" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." +msgstr "" +"Jūsų vartotojas neturi leidimų kopijuoti visus pasirinktus failus ir / ar " +"aplankus." + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "Grįžti atgal" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "Nėra jokių paskyrimo aplankų." + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "Nėra jokiu failų ir / ar aplankų kopijavimui." + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "" +"Šie failai ir / ar aplankai bus nukopijuoti į paskirtą aplanką (išlaikant jų " +"medžio struktūrą):" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "Paskyrimo aplankas:" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "Kopijuoti" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "Neleidžiama kopijuoti bylų į tą patį aplanką" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "" +"Jūsų vartotojas neturi leidimų keisti dydžius visiems pasirinktiems " +"paveikslėliams." + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "Nėra jokiu paveikslėlių dydžio keitimui." + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "Šių paveikslėlių dydis bus pakeistas:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "" +"Pasirinkite esamą miniatiūros nustatymą, arba įveskite dydžio keitimo " +"parametrus:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "" +"Įspėjimas: Paveikslėlių dydžiai bus pakeisti vietoje, ir originalas bus " +"pašalintas. Patartina atsikopijuoti paveikslėlį, kad nedingtų originalas." + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "Pakeisti dydį" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." +msgstr "" +"Jūsų vartotojas neturi leidimų perkelti visus pasirinktus failus ir / ar " +"aplankus." + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "Nėra jokiu failų ir / ar aplankų perkelimui." + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "" +"Šie failai ir / ar aplankai bus perkelti į paskirtą aplanką (išlaikant jų " +"medžio struktūrą):" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "Perkelti" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "Neleidžiama perkelti bylų į tą patį aplanką" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "Jūsų vartotojas neturi leidimų pervardinti visus pasirinktus failus." + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "Nėra jokių failų pervardinimui." + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "" +"Šie failai bus pervardinti (jie liks savo aplankuose ir pasiliks savo " +"originalius pavadinimus, pasikeis tik atvaizduojamas failo pavadinimas):" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "Pervardinti" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "Grįžti į pirminį aplanką" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "Keisti dabartinio aplanko detales" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "Keisti" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "Spausti čia kad būtų paleista paieška visai frazei" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "Ieškoti" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "Uždaryti" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "Limitas" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "Pažymėti, kad paieška būtų apribota tik dabartiniame aplanke" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "Apriboti paieška tik dabartiniame aplanke" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "Pašalinti" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "Sukuria naują aplanką" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "Naujas aplankas" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "įkelti bylas" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "Pirma turite pasirinkti aplanką" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "Pavadinimas" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "Savininkas" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "Dydis" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "Veiksmas" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "Keisti '%(item_label)s' aplanko detales" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "%(counter)s aplankas" +msgstr[1] "%(counter)s aplankai" +msgstr[2] "%(counter)s aplankų" +msgstr[3] "%(counter)s aplankų" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "%(counter)s byla" +msgstr[1] "%(counter)s bylos" +msgstr[2] "%(counter)s bylų" +msgstr[3] "%(counter)s bylų" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "Keisti aplanko detales" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "Pašalinti aplanką" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "Pasirinkti šį failą" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "Keisti '%(item_label)s' detales" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "Leidimai" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "išjungta" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "įjungta" + +#: templates/admin/filer/folder/directory_table_list.html:144 +#, fuzzy +#| msgid "Move selected files to clipboard" +msgid "URL copied to clipboard" +msgstr "Perkelti pažymėtus failus į iškarpinę" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "Kanoninis url '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "Parsisiųsti '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "Pašalinti bylą" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "Meskite bylas čia arba naudokit \"Įkelti bylas\" mygtuką" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "Meskite bylą kad įkelti į:" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "Įkelti" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "atšaukti" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "Įkelimas pavyko!" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "Įkelimas atšauktas!" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "buvęs" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "Puslapis %(number)s iš %(num_pages)s." + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "kitas" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "Pasirinkti visus %(total_count)s" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "Pridėti naują" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "Django tinklalapio administravimas" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "Ištaisykite žemiau esančias klaidas." +msgstr[1] "Ištaisykite žemiau esančias klaidas." +msgstr[2] "Ištaisykite žemiau esančias klaidas." +msgstr[3] "Ištaisykite žemiau esančias klaidas." + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "Išsaugoti" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "Iškarpinė" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "Įkopijuoti visus objektus čia" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "Perkelti visus iškarpinėje esančius failus į" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "Išvalyti iškarpinę" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "iškarpinė tuščia" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "įkelimas nepavyko" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "Tipas" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "Failo dydis" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "Pakeistas" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "Sukurtas" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "rasta" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "ir" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "atšaukti paiešką" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "Išvalyti" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "arba meskite bylą čia" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "joks failas nepasirinktas" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "Informacijos ieškojimas" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "Pasirinkti bylą" + +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" +#~ msgstr[2] "15c0f2d28d6dab1af1f6d94906beb627_pl_2" +#~ msgstr[3] "15c0f2d28d6dab1af1f6d94906beb627_pl_3" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/lt_LT/LC_MESSAGES/django.mo b/filer/locale/lt_LT/LC_MESSAGES/django.mo new file mode 100644 index 000000000..5e380751c Binary files /dev/null and b/filer/locale/lt_LT/LC_MESSAGES/django.mo differ diff --git a/filer/locale/lt_LT/LC_MESSAGES/django.po b/filer/locale/lt_LT/LC_MESSAGES/django.po new file mode 100644 index 000000000..a7dcb78dc --- /dev/null +++ b/filer/locale/lt_LT/LC_MESSAGES/django.po @@ -0,0 +1,1236 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Angelo Dini \n" +"Language-Team: Lithuanian (Lithuania) (http://app.transifex.com/divio/django-" +"filer/language/lt_LT/)\n" +"Language: lt_LT\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < " +"11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? " +"1 : n % 1 != 0 ? 2: 3);\n" + +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "" + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "" + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "" + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "" + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "" + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "" + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "" + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "" + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "" + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "" + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "" + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "" + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "" + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "" + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "" + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "" + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "" + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "" + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "" + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "" + +#: models/abstract.py:91 +msgid "image" +msgstr "" + +#: models/abstract.py:92 +msgid "images" +msgstr "" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "" + +#: models/filemodels.py:116 +msgid "description" +msgstr "" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "" + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "" + +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:144 +msgid "URL copied to clipboard" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "" + +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" +#~ msgstr[2] "15c0f2d28d6dab1af1f6d94906beb627_pl_2" +#~ msgstr[3] "15c0f2d28d6dab1af1f6d94906beb627_pl_3" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/nb/LC_MESSAGES/django.mo b/filer/locale/nb/LC_MESSAGES/django.mo new file mode 100644 index 000000000..cc24295a7 Binary files /dev/null and b/filer/locale/nb/LC_MESSAGES/django.mo differ diff --git a/filer/locale/nb/LC_MESSAGES/django.po b/filer/locale/nb/LC_MESSAGES/django.po new file mode 100644 index 000000000..05d3f22b3 --- /dev/null +++ b/filer/locale/nb/LC_MESSAGES/django.po @@ -0,0 +1,1256 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +# Eirik Krogstad , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Eirik Krogstad , 2013\n" +"Language-Team: Norwegian Bokmål (http://app.transifex.com/divio/django-filer/" +"language/nb/)\n" +"Language: nb\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" + +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "" + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "Avansert" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" +"Du må velge noen elementer for å utføre handlinger på dem. Ingen elementer " +"er endret." + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "%(total_count)s valgt" +msgstr[1] "Alle %(total_count)s valgt" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "0 av %(cnt)s valgt" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "Ingen handling valgt." + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "Flyttet %(count)d filer til utklippstavlen." + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "Flytt valgte filer til utklippstavlen" + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "Fjernet tillatelser for %(count)d filer." + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "Satte tillatelser for %(count)d filer." + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "Sett tillatelser for valgte filer" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "Fjern tillatelser for valgte filer" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "Slettet %(count)d filer og/eller mapper." + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "Kan ikke slette filer og/eller mapper" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "Er du sikker?" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "Slett filer og/eller mapper" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "Slett valgte filer og/eller mapper" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" +"Flyttet %(count)d filer og/eller mapper til mappen \"%(destination)s\"." + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "Flytt filer og/eller mapper" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "Flytt valgte filer og/eller mapper" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "Endret navn på %(count)d filer." + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "Endre navn på filer" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" +"Kopierte %(count)d filer og/eller mapper til mappen \"%(destination)s\"." + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "Kopier filer og/eller mapper" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "Kopier valgte filer og/eller mapper" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "Endret størrelse på %(count)d bilder." + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "Endre størrelse på bilder" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "Endre størrelse på valgte bilder" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "Endelse som vil tilføyes filnavn på kopierte filer." + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "" +"Endelse bør være en gyldig, enkel del av filnavnet med små bokstaver, som " +"\"%(valid)s\"." + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "Ugyldig nøkkel \"%(key)s\" for endring av navn." + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "Ugyldig format for endring av navn: %(error)s" + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "miniatyrbildevalg" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "bredde" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "høyde" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "beskjæring" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "oppskalering" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "Miniatyrbildevalg eller parametre for endring av størrelse må velges." + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "Fokuseringsområde" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "" + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "" + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "" + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "" + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "En mappe med dette navnet eksisterer allerede." + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "Filer" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "standard alternativtekst" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "standard undertekst" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "fokuseringsområde" + +#: models/abstract.py:91 +msgid "image" +msgstr "bilde" + +#: models/abstract.py:92 +msgid "images" +msgstr "bilder" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "bruker" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "filer" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "utklippstavle" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "utklippstavler" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "fil" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "element på utklippstavle" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "elementer på utklippstavle" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "mappe" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "filstørrelse" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "sha1" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "har alle påkrevde data" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "originalt filnavn" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "navn" + +#: models/filemodels.py:116 +msgid "description" +msgstr "beskrivelse" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "eier" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "lastet opp" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "endret" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "Tillatelser er deaktivert" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "opprettet" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "Mappe" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "Mapper" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "alle elementer" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "kun dette elementet" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "dette elementet og alle underliggende nivå" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "type" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "gruppe" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "alle" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "kan lese" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "kan redigere" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "kan legge til undernivåer" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "tillatelse for mappe" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "tillatelser for mappe" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "" + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "dato bildet ble tatt" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "opphavsperson" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "må alltid publisere opphavsperson" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "må alltid publisere opphavsrett" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "filer med manglende metadata" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "rot" + +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "Utfør den valgte handlingen" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "Utfør" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "Klikk her for å velge objekter på tvers av alle sider" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "Velg alle %(total_count)s filer og/eller mapper" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "Tøm utvalg" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "Gå tilbake til administrasjonssiden" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "Hjem" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "Gå tilbake til Filer" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "Gå tilbake til rotmappen" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "Gå tilbake til mappen \"%(folder_name)s\"" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" +"Å slette de valgte filene og/eller mappene ville resultere i sletting av " +"relaterte objekter, men din konto har ikke tillatelse til å slette objekter " +"av følgende typer:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "" +"Å slette de valgte filene og/eller mappene ville kreve å slette følgende " +"beskyttede relaterte objekter:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "" +"Er du sikker på at du vil slette de valgte filene og/eller mappene? Alle de " +"følgende objektene og deres relaterte elementer vil bli slettet:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "Historie" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "Se på nettstedet" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "Gå tilbake til" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "administrasjonssiden" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "Mappeikon" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." +msgstr "" +"Din konto har ikke tillatelse til å kopiere alle de valgte filene og/eller " +"mappene." + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "Det er ingen målmapper tilgjengelig." + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "Det er ingen filer og/eller mapper å kopiere." + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "" +"De følgende filene og/eller mappene vil bli kopiert til en målmappe " +"(mappestruktur vil beholdes):" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "Målmappe:" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "Kopier" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "" +"Din konto har ikke tillatelse til å endre størrelse på alle valgte bilder." + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "Det er ingen bilder å endre størrelse på." + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "De følgende bildene vil få endret størrelse:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "" +"Velg et eksisterende miniatyrbildevalg eller skriv inn parametre for endring " +"av størrelse:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "" +"Advarsel: Bilder vil få sin størrelse endret, og originalene vil gå tapt. " +"Det kan være ønskelig å først gjøre en kopi for å beholde originalene." + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "Endre størrelse" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." +msgstr "" +"Din konto har ikke tillatelse til å flytte alle de valgte filene og/eller " +"mappene." + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "Det er ingen filer og/eller mapper å flytte." + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "" +"De følgende filene og/eller mappene vil bli flyttet til en målmappe " +"(mappestruktur vil beholdes):" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "Flytt" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "" +"Din konto har ikke tillatelse til å endre navn på alle de valgte filene." + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "Det er ingen filer å endre navn på." + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "" +"De følgende filene vil få endret navn (de vil forbli på samme sted og " +"beholde originalt filnavn, bare visningsnavn vil endres):" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "Endre navn" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "Gå tilbake til overordnet nivå" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "Endre detaljer for gjeldende mappe" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "Endre" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "Søk" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "Slett" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "Legger til en ny mappe" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "Ny mappe" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "Navn" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "Eier" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "Endre detaljer for mappen \"%(item_label)s\"" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "" +msgstr[1] "" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "" +msgstr[1] "" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "Velg denne filen" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "Endre detaljer for \"%(item_label)s\"" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "Tillatelser" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "deaktivert" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "aktivert" + +#: templates/admin/filer/folder/directory_table_list.html:144 +#, fuzzy +#| msgid "Move selected files to clipboard" +msgid "URL copied to clipboard" +msgstr "Flytt valgte filer til utklippstavlen" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "Last opp" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "forrige" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "neste" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "Legg til ny" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "Vennligst rett feilen under" +msgstr[1] "Vennligst rett feilene under." + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "Lagre" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "Utklippstavle" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "Lim inn alle elementer her" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "Flytt alle filer på utklippstavlen til" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "utklippstavlen er tom" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "feil ved opplasting" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "funnet" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "og" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "avbryt søk" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "Tøm" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "ingen fil valgt" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "Slå opp" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "" + +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/nl_NL/LC_MESSAGES/django.mo b/filer/locale/nl_NL/LC_MESSAGES/django.mo new file mode 100644 index 000000000..c9e62df2f Binary files /dev/null and b/filer/locale/nl_NL/LC_MESSAGES/django.mo differ diff --git a/filer/locale/nl_NL/LC_MESSAGES/django.po b/filer/locale/nl_NL/LC_MESSAGES/django.po new file mode 100644 index 000000000..0cbda5a3f --- /dev/null +++ b/filer/locale/nl_NL/LC_MESSAGES/django.po @@ -0,0 +1,1245 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +# Alexander Schoemaker , 2012 +# Alexander Schoemaker , 2012 +# Edwin Janssen, 2023 +# Evelijn Saaltink , 2017 +# Jeroen, 2018 +# Maikel Wever, 2013 +# Maikel Wever, 2013 +# Stefan van den Eertwegh , 2023 +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Stefan van den Eertwegh , 2023\n" +"Language-Team: Dutch (Netherlands) (http://app.transifex.com/divio/django-filer/language/nl_NL/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nl_NL\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: admin/clipboardadmin.py:17 +#| msgid "" +#| "ccount doesn't have permissions to rename all of the selected files." +msgid "You do not have permission to upload files." +msgstr "Je hebt geen rechten om bestanden te uploaden." + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "Kan map niet vinden om te uploaden. Herlaad de pagina en probeer het opnieuw." + +#: admin/clipboardadmin.py:20 +msgid "" +"Can't use this folder, Permission Denied. Please select another folder." +msgstr "Kan deze map niet gebruiken, rechten geweigerd. Kies een andere map." + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "Geavanceerd" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "canonieke URL" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "De actie kan niet worden uitgevoerd omdat er zijn geen items geselecteerd." + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "%(total_count)s geselecteerd" +msgstr[1] "Alle %(total_count)s geselecteerd" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "Inhoud van map %(folder_name)s" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "0 van %(cnt)s geselecteerd" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "Geen actie geselecteerd." + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "%(count)d bestanden zijn succesvol verplaatst naar het klembord." + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "Verplaats geselecteerde bestanden naar het klembord" + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "Toegangsrechten succesvol uitgeschakeld voor %(count)d bestanden." + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "Toegangsrechten succesvol ingeschakeld voor %(count)d bestanden." + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "Schakel toegangsrechten in voor geselecteerde bestanden" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "Schakel toegangsrechten uit voor geselecteerde bestanden" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "%(count)d bestanden en/of mappen zijn succesvol verwijderd." + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "Bestanden en/of mappen kunnen niet worden verwijderd" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "Weet je het zeker?" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "Verwijder bestanden en/of mappen" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "Verwijder geselecteerde bestanden en/of mappen" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "Er bestaan al mappen met de namen %s op de geselecteerde bestemming" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "%(count)d bestanden en of mappen zijn succesvol verplaatst naar map '%(destination)s'." + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "Verplaats bestanden en/of mappen" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "Verplaats geselecteerde bestanden en/of mappen" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "%(count)d bestanden zijn succesvol hernoemd." + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "Hernoem bestanden" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "%(count)d bestanden en/of mappen zijn succesvol gekopieerd naar map '%(destination)s'." + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "Kopieer bestanden en/of mappen" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "Kopieer geselecteerde bestanden en/of mappen" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "Afmetingen van %(count)d afbeeldingen zijn succesvol aangepast." + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "Afmetingen aanpassen" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "Afmetingen aanpassen van geselecteerde afbeeldingen" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "Achtervoegsel wordt toegevoegd aan bestandsnaam van gekopieerde bestanden" + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "Achtervoegsel moet een geldige waarde zijn in kleine letters, bv. \"%(valid)s\"." + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "Type \"%(key)s\" voor het hernoemen van bestandsnamen is ongeldig." + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "Ongeldige waarde voor het hernoemen van bestandsnamen: %(error)s." + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "thumbnail optie" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "breedte" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "hoogte" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "uitsnijden" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "opschalen" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "Thumbnail optie of afmetingsopties moet zijn geselecteerd" + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "Locatie van onderwerp" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "Locatie van het hoofdonderwerp van de scène. Formaat: \"x,y\"." + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "Ongeldig locatieformaat van het onderwerp" + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "Locatie van het onderwerp bevindt zich buiten de afbeelding." + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "Je invoer: \"{subject_location}\"." + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "Wie" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "Wat" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "Er bestaat al een map met deze naam." + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "Bestandsbeheer" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "Mediabibliotheek" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "standaard alt. tekst" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "standaard titel" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "locatie van onderwerp" + +#: models/abstract.py:91 +msgid "image" +msgstr "afbeelding" + +#: models/abstract.py:92 +msgid "images" +msgstr "afbeeldingen" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "Afbeelding formaat niet herkend of afbeelding grootte overtreft limiet van %(max_pixels)d miljoen pixels bij een factor twee of meer. Voor opnieuw uploaden, check bestandsformaat of wijzig grootte afbeelding van %(width)d x %(height)d resolutie of lager." + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "Afbeelding grootte (%(pixels)d miljoen pixels) overtreft limiet van %(max_pixels)d miljoen pixels. Voor het opnieuw uploaden, afbeelding grootte van %(width)d x %(height)d resolutie of lager." + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "gebruiker" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "bestanden" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "klembord" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "klemborden" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "bestand" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "klembord item" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "klembord items" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "map" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "bestandsgrootte" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "sha1" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "heeft allen verplichte eigenschappen" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "oorspronkelijke bestandsnaam" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "naam" + +#: models/filemodels.py:116 +msgid "description" +msgstr "omschrijving" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "eigenaar" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "geüpload op" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "gewijzigd op" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "Toegangsrechten uitgeschakeld" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "Schakel controle op toegangsrechten uit voor dit bestand. Het bestand zal publiek toegankelijk zijn voor iedereen" + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "ouder" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "aangemaakt op" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "Map" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "Mappen" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "alle items" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "alleen dit item" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "dit item en alle onderliggende items" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "overerven" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "toestaan" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "afwijzen" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "type" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "groep" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "iedereen" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "mag lezen" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "mag wijzigen" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "mag onderliggende items toevoegen" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "toegangsrecht folder" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "toegangsrechten folder" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "Map kan niet geselecteerd worden met type \"alle items\"." + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "Map moet geselecteerd worden wanneer type niet \"alle items\" is." + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "Gebruiker of groep kan niet geselecteerd worden samen met \"iedereen\"." + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "Ten minste één gebruiker, groep of \"iedereen\" moet worden geselecteerd." + +#: models/foldermodels.py:360 +#| msgid "Folders" +msgid "All Folders" +msgstr "Alle Mappen" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "Logisch Pad" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "Gebruiker:{user}" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "Groep: {group}" + +#: models/foldermodels.py:375 +#| msgid "everybody" +msgid "Everybody" +msgstr "Iedereen" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "Bewerken" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "Lezen" + +#: models/foldermodels.py:390 +#| msgid "can add children" +msgid "Add children" +msgstr "Toevoegen kinderen" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "datum" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "auteur" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "naam auteur altijd publiceren" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "auteursrechten altijd publiceren" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "breedte in pixel." + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "hoogte in pixel." + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "thumbnail-opties" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "Ongesorteerde uploads" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "bestanden met ontbrekende meta gegevens" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "hoofdmap" + +#: settings.py:273 +msgid "Show table view" +msgstr "Toon tabel weergave" + +#: settings.py:278 +#| msgid "thumbnail option" +msgid "Show thumbnail view" +msgstr "Toon thumbnail weergave" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "Geselecteerde actie uitvoeren" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "Uitvoeren" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "Klik hier om objecten over alle pagina's te selecteren" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "Selecteer alle %(total_count)s bestanden en/of mappen" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "Selectie wissen" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "Ga terug naar admin homepage" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "Home" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "Ga terug naar Bestandsbeheer" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "Ga terug naar de hoofdmap" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "Ga terug naar map '%(folder_name)s'" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "Duplicaten" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "Het verwijderen van de geselecteerde bestanden en/of mappen resulteert in het verwijderen van gerelateerde objecten. Je hebt echter geen toegangsrechten voor het verwijderen van de volgende objecttypes:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "Het verwijderen van de geselecteerde bestanden en/of mappen leidt tot het verwijderen van de volgende beschermde gerelateerde objecten:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "Weet je zeker dat je de geselecteerde bestanden en/of folders wilt verwijderen? Alle volgende objecten en gerelateerde items zullen worden verwijderd: " + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "Nee, ga terug" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "Ja, ik weet het zeker" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "Geschiedenis" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "Bekijk op site" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "Ga terug naar" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "admin homepage" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "Map icoon" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files " +"and/or folders." +msgstr "Je account heeft geen toegangsrechten voor het kopiëren van de geselecteerde bestanden en/of mappen" + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "Neem me mee terug" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "Er zijn geen bestemmingsmappen beschikbaar." + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "Er zijn geen bestanden en/of mappen beschikbaar om te kopiëren." + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "De volgende bestanden en/of mappen zullen worden gekopieerd naar een bestemmingsmap (structuur blijft behouden):" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "Bestemmingsmap:" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "Kopiëren" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "Het is niet toegestaan om bestanden naar dezelfde map te kopiëren" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "Je account heeft geen toegangsrechten om afmetingen van alle geselecteerde afbeeldingen aan te passen." + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "Er zijn geen afbeeldingen beschikbaar voor het aanpassen van afmetingen." + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "De afmetingen van de volgende afbeeldingen zullen worden aangepast:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "Kies een bestaande thumbnail optie of voer afmetingsopties in:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "Waarschuwing: bestaande afmetingen van afbeeldingen zullen worden aangepast. Oorspronkelijke bestanden zullen verloren gaan. Maak eventueel eerst een kopie om de oorspronkelijke bestanden te behouden." + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "Afmetingen aanpassen" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files " +"and/or folders." +msgstr "Je account heeft geen toegangsrechten om alle geselecteerde bestanden en/of mappen te verplaatsen." + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "Er zijn geen bestanden en/of mappen beschikbaar om te verplaatsen." + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "De volgende bestanden en/of mappen zullen worden verplaatst naar een bestemmingsmap (huidige mapstructuur blijft behouden): " + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "Verplaatsen" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "Het is niet toegestaan om bestanden naar dezelfde map te verplaatsen" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "Je account heeft onvoldoende toegangsrechten om alle geselecteerde bestanden te hernoemen." + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "Er zijn geen bestanden beschikbaar om te hernoemen." + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "De volgende bestanden zullen worden hernoemd (de oorspronkelijke mapstructuur en bestandsnamen blijven behouden, alleen de weergave zal worden gewijzigd):" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "Hernoemen" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "Ga terug naar de bovenliggende folder" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "Wijzig eigenschappen van huidige map" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "Wijzigen" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "Klik hier om een zoekopdracht te doen voor de ingevoerde woorden" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "Zoeken" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "Sluiten" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "Limiteren" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "Vink het aan om de zoekopdracht te beperken tot de huidige map" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "Zoekopdracht beperken tot huidige map" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "Verwijderen" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "Voegt een nieuwe map toe" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "Nieuwe map" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "Bestanden uploaden" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "Je moet eerst een map selecteren" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "Naam" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "Eigenaar" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "Grootte" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "Actie" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "Wijzig eigenschappen map '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "%(counter)s map" +msgstr[1] "%(counter)s mappen" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "%(counter)s bestand" +msgstr[1] "%(counter)s bestanden" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "Wijzig eigenschappen van de map" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "Verwijder map" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "Selecteer dit bestand" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "Wijzig eigenschappen '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "Toegangsrechten" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "uitgeschakeld" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "ingeschakeld" + +#: templates/admin/filer/folder/directory_table_list.html:144 +#| msgid "Move selected files to clipboard" +msgid "URL copied to clipboard" +msgstr "URL gekopieerd naar het klembord" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +#| msgid "Change '%(item_label)s' details" +msgid "Canonical url '%(item_label)s'" +msgstr "Gebruikelijke url '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +#| msgid "Change '%(item_label)s' details" +msgid "Download '%(item_label)s'" +msgstr "Download '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "Verwijder bestand" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "Sleep hier bestanden naartoe of gebruik de \"Bestanden uploaden\"-knop" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "Sleep je bestand om te uploaden naar:" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "Uploaden" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "annuleer" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "Upload succesvol!" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "Upload geannuleerd!" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "vorige" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "Pagina %(number)s van %(num_pages)s." + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "volgende" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "Selecteer alle %(total_count)s" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +#| msgid "Select this file" +msgid "Select all" +msgstr "Alles selecteren" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +#| msgid "Filer" +msgid "Files" +msgstr "Bestanden" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "Toevoegen nieuwe" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "Django site beheer" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "Herstel onderstaande fout." +msgstr[1] "Herstel onderstaande fouten." + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "Opslaan" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "Je browser ondersteunt geen audio." + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "Je browser ondersteunt geen video." + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "Klembord" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "Alle items hier plakken" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "Verplaats alle klembord items naar" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "Leeg klembord" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "het klembord is leeg" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "upload mislukt" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "Download" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "Uitvouwen" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +#| msgid "file missing" +msgid "File is missing" +msgstr "Bestand ontbreekt" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "Type" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "Bestandsgrootte" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "Gewijzigd" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "Aangemaakt" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "gevonden" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "en" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "annuleer zoekopdracht" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "Wissen" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "of sleep je bestand hier naartoe" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "geen bestand geselecteerd" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "Opzoeken" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "Kies bestand" + +#: templates/admin/filer/widgets/admin_folder.html:16 +#| msgid "Choose File" +msgid "Choose Folder" +msgstr "Kies Map" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "Bestand \"{file_name}\": Upload geweigerd door het beveiligingsbeleid van de site" + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "Bestand \"{file_name}\": {file_type} upload geweigerd door het beveiligingsbeleid van de site" + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "Bestand \"{file_name}\": HTML upload geweigerd door het beveiligingsbeleid van de site" + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "Bestand \"{file_name}\": Afgewezen wegens mogelijke kwetsbaarheid voor cross-site scripting" + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "Bestand \"{file_name}\": SVG bestandsformaat niet herkend" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/nn/LC_MESSAGES/django.mo b/filer/locale/nn/LC_MESSAGES/django.mo new file mode 100644 index 000000000..379659ff7 Binary files /dev/null and b/filer/locale/nn/LC_MESSAGES/django.mo differ diff --git a/filer/locale/nn/LC_MESSAGES/django.po b/filer/locale/nn/LC_MESSAGES/django.po new file mode 100644 index 000000000..255a1f963 --- /dev/null +++ b/filer/locale/nn/LC_MESSAGES/django.po @@ -0,0 +1,1253 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +# Eirik Krogstad , 2013 +# Eirik Krogstad , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Eirik Krogstad , 2013\n" +"Language-Team: Norwegian Nynorsk (http://app.transifex.com/divio/django-" +"filer/language/nn/)\n" +"Language: nn\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" + +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "" + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "Avansert" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" +"Element må vere vald for å utføre handlingar på dei. Ingen element vart " +"endra." + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "%(total_count)s vald" +msgstr[1] "Alle %(total_count)s vald" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "0 av %(cnt)s vald" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "Ingen handling vald." + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "Flytta %(count)d filer til utklippstavla." + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "Flytt valde filer til utklippstavla" + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "Fjerna løyve for %(count)d filer." + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "Satte løyve for %(count)d filer." + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "Sett løyve for valde filer" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "Fjern løyve for valde filer" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "Sletta %(count)d filer og/eller mapper." + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "Kan ikkje slette filer og/eller mapper" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "Er du sikker?" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "Slett filer og/eller mapper" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "Slett valde filer og/eller mapper" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "Flytta %(count)d filer og/eller mapper til mappa \"%(destination)s\"." + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "Flytt filer og/eller mapper" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "Flytt valde filer og/eller mapper" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "Endra namn på %(count)d filer." + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "Endre namn på filer" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" +"Kopierte %(count)d filer og/eller mapper til mappa \"%(destination)s\"." + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "Kopier filer og/eller mapper" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "Kopier valde filer og/eller mapper" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "Endra storleik på %(count)d bilete." + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "Endre storleik på bilete" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "Endre storleik på valde bilete" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "Ending som vert tilføyd filnamn på kopierte filer." + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "" +"Ending bør vere ein gyldig, enkel del av filnamnet med små bokstavar, som " +"\"%(valid)s\"." + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "Ugyldig nykel \"%(key)s\" for endring av namn." + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "Ugyldig format for endring av namn: %(error)s" + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "miniatyrbileteval" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "breidd" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "høgd" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "skjering" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "oppskalering" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "Miniatyrbileteval eller parametrar for endring av storleik må veljast." + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "Fokuseringsområde" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "" + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "" + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "" + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "" + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "Ein mappe med dette namnet eksisterer allereie." + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "Filer" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "standard alternativtekst" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "standard undertekst" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "fokuseringsområde" + +#: models/abstract.py:91 +msgid "image" +msgstr "bilete" + +#: models/abstract.py:92 +msgid "images" +msgstr "bilete" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "brukar" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "filer" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "utklippstavle" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "utklippstavler" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "fil" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "element på utklippstavle" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "element på utklippstavle" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "mappe" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "filstorleik" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "sha1" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "har alle påkravde data" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "originalt filnamn" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "namn" + +#: models/filemodels.py:116 +msgid "description" +msgstr "beskriving" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "eigar" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "lasta opp" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "endra" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "Løyve er deaktivert" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "oppretta" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "Mappe" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "Mapper" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "alle element" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "berre dette elementet" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "dette elementet og alle underliggjande nivå" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "type" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "gruppe" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "alle" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "kan lese" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "kan redigere" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "kan leggje til undernivå" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "løyve for mappe" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "løyve for mappe" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "" + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "dato biletet vert tatt" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "opphavsperson" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "må alltid publisere opphavsperson" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "må alltid publisere opphavsrett" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "filer med manglande metadata" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "rot" + +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "Utfør den valde handlinga" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "Utfør" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "Klikk her for å velje objekt på tvers av alle sider" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "Vel alle %(total_count)s filer og/eller mapper" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "Tøm utval" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "Gå tilbake til administrasjonssida" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "Heim" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "Gå tilbake til Filer" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "Gå tilbake til rotmappa" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "Gå tilbake til mappa \"%(folder_name)s\"" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" +"Å slette dei valde filene og/eller mappene ville resultere i sletting av " +"relaterte objekt, men din konto har ikkje løyve til å slette objekt av " +"følgjande typer:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "" +"Å slette dei valde filene og/eller mappene ville kreve å slette følgjande " +"beskytta relaterte objekt:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "" +"Er du sikker på at du vil slette dei valde filene og/eller mappene? Alle dei " +"følgjande objekta og deira relaterte element vil verte sletta:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "Historie" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "Se på nettstaden" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "Gå tilbake til" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "administrasjonssida" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "Mappeikon" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." +msgstr "" +"Din konto har ikkje løyve til å kopiere alle dei valde filene og/eller " +"mappene." + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "Det er ingen målmapper tilgjengelig." + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "Det er ingen filer og/eller mapper å kopiere." + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "" +"Dei følgjande filene og/eller mappene vil verte kopiert til ein målmappe " +"(mappestruktur vil behaldes):" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "Målmappe:" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "Kopier" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "Din konto har ikkje løyve til å endre storleik på alle valde bilete." + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "Det er ingen bilete å endre storleik på." + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "Dei følgjande bileta vil få endra storleik:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "" +"Vel eit eksisterande miniatyrbileteval eller skriv inn parametrar for " +"endring av storleik:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "" +"Åtvaring: Bileta vil få sin storleik endra, og originalane vil gå tapt. Det " +"kan være ønskjeleg å først gjere ein kopi for å behalde originalane." + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "Endre storleik" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." +msgstr "" +"Din konto har ikke løyve til å flytte alle dei valde filene og/eller mappene." + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "Det er ingen filer og/eller mapper å flytte." + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "" +"Dei følgjande filene og/eller mappene vil verte flytta til ein målmappe " +"(mappestruktur vil behaldes):" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "Flytt" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "Din konto har ikkje løyve til å endre namn på alle dei valde filene." + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "Det er ingen filer å endre namn på." + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "" +"Dei følgjande filene vil få endra namn (dei vil framleis vere på samme stad " +"og behalde originalt filnamn, berre visningsnamn vil verte endra):" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "Endre namn" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "Gå tilbake til overordna nivå" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "Endre detaljar for gjeldande mappe" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "Endre" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "Søk" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "Slett" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "Legg til ein ny mappe" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "Ny mappe" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "Namn" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "Eigar" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "Endre detaljar for mappen \"%(item_label)s\"" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "" +msgstr[1] "" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "" +msgstr[1] "" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "Vel denne filen" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "Endre detaljar for \"%(item_label)s\"" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "Løyve" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "deaktivert" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "aktivert" + +#: templates/admin/filer/folder/directory_table_list.html:144 +#, fuzzy +#| msgid "Move selected files to clipboard" +msgid "URL copied to clipboard" +msgstr "Flytt valde filer til utklippstavla" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "Last opp" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "førre" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "neste" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "Legg til ny" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "Ver venleg og rett feilen under" +msgstr[1] "Ver venleg og rett feila under." + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "Lagre" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "Utklippstavle" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "Lim inn alle element her" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "Flytt alle filer på utklippstavla til" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "utklippstavla er tom" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "feil ved opplasting" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "funne" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "og" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "avbryt søk" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "Tøm" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "ingen fil vald" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "Slå opp" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "" + +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/pl/LC_MESSAGES/django.mo b/filer/locale/pl/LC_MESSAGES/django.mo index 6307dfc78..99ec9f2ea 100644 Binary files a/filer/locale/pl/LC_MESSAGES/django.mo and b/filer/locale/pl/LC_MESSAGES/django.mo differ diff --git a/filer/locale/pl/LC_MESSAGES/django.po b/filer/locale/pl/LC_MESSAGES/django.po index 955e1f67c..1f59250c7 100644 --- a/filer/locale/pl/LC_MESSAGES/django.po +++ b/filer/locale/pl/LC_MESSAGES/django.po @@ -3,485 +3,636 @@ # This file is distributed under the same license as the PACKAGE package. # # Translators: -# crunchorn , 2010. +# Translators: +# Translators: +# crunchorn , 2010 +# Grzegorz Biały , 2017 +# Mateusz Marzantowicz , 2013 +# Piotr Wojcik , 2016 msgid "" msgstr "" -"Project-Id-Version: django-filer\n" +"Project-Id-Version: django Filer\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-07-13 19:10+0200\n" -"PO-Revision-Date: 2012-09-03 20:12+0100\n" -"Last-Translator: Stefan Foulis \n" -"Language-Team: LANGUAGE \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Grzegorz Biały , 2017\n" +"Language-Team: Polish (http://app.transifex.com/divio/django-filer/language/" +"pl/)\n" +"Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Language: pl\n" -"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " -"|| n%100>=20) ? 1 : 2);\n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && " +"(n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && " +"n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" -#: views.py:103 -msgid "Folder with this name already exists." +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." msgstr "" -#: admin/fileadmin.py:41 +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 msgid "Advanced" msgstr "Zaawansowane" -#: admin/folderadmin.py:324 admin/folderadmin.py:427 +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "kanoniczny URL" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 msgid "" "Items must be selected in order to perform actions on them. No items have " "been changed." msgstr "" +"Należy zaznaczyć elementy aby wykonań na nich jakąś akcję. Nie zaznaczono " +"żadnych elementów." -#: admin/folderadmin.py:344 +#: admin/folderadmin.py:434 #, python-format msgid "%(total_count)s selected" msgid_plural "All %(total_count)s selected" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zaznaczono %(total_count)s" +msgstr[1] "zaznaczono %(total_count)s" +msgstr[2] "Zaznaczono wszystkie %(total_count)s" +msgstr[3] "Zaznaczono wszystkie %(total_count)s" -#: admin/folderadmin.py:377 +#: admin/folderadmin.py:460 #, python-format -msgid "0 of %(cnt)s selected" +msgid "Directory listing for %(folder_name)s" msgstr "" -#: admin/folderadmin.py:456 +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "0 z %(cnt)s zaznaczonych" + +#: admin/folderadmin.py:612 msgid "No action selected." -msgstr "" +msgstr "Nie zaznaczono akcji." -#: admin/folderadmin.py:497 +#: admin/folderadmin.py:664 #, python-format msgid "Successfully moved %(count)d files to clipboard." -msgstr "" +msgstr "Pomyślnie przeniesiono %(count)d plików do schowka." -#: admin/folderadmin.py:503 +#: admin/folderadmin.py:669 msgid "Move selected files to clipboard" -msgstr "" +msgstr "Przenieś zaznaczone pliki do schowka" -#: admin/folderadmin.py:537 +#: admin/folderadmin.py:709 #, python-format msgid "Successfully disabled permissions for %(count)d files." -msgstr "" +msgstr "Pomyślnie wyłączono uprawnienia dla %(count)d plików." -#: admin/folderadmin.py:541 +#: admin/folderadmin.py:711 #, python-format msgid "Successfully enabled permissions for %(count)d files." -msgstr "" +msgstr "Pomyślnie włączono uprawnienia dla %(count)d plików." -#: admin/folderadmin.py:550 +#: admin/folderadmin.py:719 msgid "Enable permissions for selected files" -msgstr "" +msgstr "Włącz uprawnienia dla wybranych plików" -#: admin/folderadmin.py:555 +#: admin/folderadmin.py:725 msgid "Disable permissions for selected files" -msgstr "" +msgstr "Wyłącz uprawnienia dla wybranych plików" -#: admin/folderadmin.py:623 +#: admin/folderadmin.py:789 #, python-format msgid "Successfully deleted %(count)d files and/or folders." -msgstr "" +msgstr "Pomyślnie usunięto %(count)d plików i/lub katalogów." -#: admin/folderadmin.py:630 +#: admin/folderadmin.py:794 msgid "Cannot delete files and/or folders" -msgstr "" +msgstr "Nie można usunąć plików i/lub katalogów" -#: admin/folderadmin.py:632 +#: admin/folderadmin.py:796 msgid "Are you sure?" -msgstr "" +msgstr "Czy na pewno?" -#: admin/folderadmin.py:637 +#: admin/folderadmin.py:802 msgid "Delete files and/or folders" -msgstr "" +msgstr "Usuń pliki i/lub katalogi" -#: admin/folderadmin.py:656 +#: admin/folderadmin.py:823 msgid "Delete selected files and/or folders" -msgstr "" +msgstr "Usuń zaznaczone pliki i/lub katalogi" -#: admin/folderadmin.py:771 +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "Katalogi z nazwami %s już istnieją w podanej lokacji" + +#: admin/folderadmin.py:934 #, python-format msgid "" "Successfully moved %(count)d files and/or folders to folder " "'%(destination)s'." msgstr "" +"Pomyślnie przeniesiono %(count)d plików i/lub katalogów do '%(destination)s'." -#: admin/folderadmin.py:778 admin/folderadmin.py:780 +#: admin/folderadmin.py:942 admin/folderadmin.py:944 msgid "Move files and/or folders" -msgstr "" +msgstr "Przenieś pliki i/lub katalogi" -#: admin/folderadmin.py:797 +#: admin/folderadmin.py:959 msgid "Move selected files and/or folders" -msgstr "" +msgstr "Przenieś zaznaczone pliki i/lub katalogi" -#: admin/folderadmin.py:854 +#: admin/folderadmin.py:1016 #, python-format msgid "Successfully renamed %(count)d files." -msgstr "" +msgstr "Pomyślnie zmieniono nazwę %(count)d plików." -#: admin/folderadmin.py:862 admin/folderadmin.py:864 admin/folderadmin.py:881 +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 msgid "Rename files" -msgstr "" +msgstr "Zmień nazwy plików" -#: admin/folderadmin.py:975 +#: admin/folderadmin.py:1137 #, python-format msgid "" "Successfully copied %(count)d files and/or folders to folder " "'%(destination)s'." msgstr "" +"Pomyślnie skopiowano %(count)d plików i/lub katalogów di '%(destination)s'." -#: admin/folderadmin.py:989 admin/folderadmin.py:991 +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 msgid "Copy files and/or folders" -msgstr "" +msgstr "Skopiuj pliki i/lub katalogi" -#: admin/folderadmin.py:1010 +#: admin/folderadmin.py:1174 msgid "Copy selected files and/or folders" -msgstr "" +msgstr "Skopiuj zaznaczone pliki i/lub katalogi" -#: admin/folderadmin.py:1105 +#: admin/folderadmin.py:1279 #, python-format msgid "Successfully resized %(count)d images." -msgstr "" +msgstr "Pomyślnie zmieniono rozmiar %(count)d obrazów." -#: admin/folderadmin.py:1113 admin/folderadmin.py:1115 +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 msgid "Resize images" -msgstr "" +msgstr "Zmień rozmiar obrazów" -#: admin/folderadmin.py:1133 +#: admin/folderadmin.py:1303 msgid "Resize selected images" -msgstr "" +msgstr "Zmień rozmiar zaznaczonych obrazów" -#: admin/forms.py:26 +#: admin/forms.py:24 msgid "Suffix which will be appended to filenames of copied files." -msgstr "" +msgstr "Przyrostek, który zostanie dodany do nazw skopiowanych plików." -#: admin/forms.py:33 +#: admin/forms.py:31 #, python-format msgid "" "Suffix should be a valid, simple and lowercase filename part, like " "\"%(valid)s\"." msgstr "" +"Przyrostek powinien być poprawną, prostą, składającą się z małych liter " +"częścią nazwy pliku, np. \"%(valid)s\"" -#: admin/forms.py:54 +#: admin/forms.py:52 #, python-format msgid "Unknown rename format value key \"%(key)s\"." -msgstr "" +msgstr "Nieznany format klucza \"%(key)s\"." -#: admin/forms.py:56 +#: admin/forms.py:54 #, python-format msgid "Invalid rename format: %(error)s." -msgstr "" +msgstr "Niepoprawny format: %(error)s." -#: admin/forms.py:62 +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 msgid "thumbnail option" -msgstr "" +msgstr "opcje miniatur" -#: admin/forms.py:63 +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 msgid "width" -msgstr "" +msgstr "szerokość" -#: admin/forms.py:64 +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 msgid "height" -msgstr "" +msgstr "wysokość" -#: admin/forms.py:65 +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 msgid "crop" -msgstr "" +msgstr "przytnij" -#: admin/forms.py:66 +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 msgid "upscale" -msgstr "" +msgstr "skaluj" -#: admin/forms.py:71 +#: admin/forms.py:79 msgid "Thumbnail option or resize parameters must be choosen." +msgstr "Opcja miniatury albo parametry zmiany rozmiaru muszą być określone." + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "Współrzędne obiektu" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "Współrzędne głównego obiektu prezentowanej sceny. Format: \"x,y\"." + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "Niepoprawny format współrzędnych obiektu." + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "Współrzędne obiektu znajdują się poza obrazem." + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "Twój wpis: \"{subject_location}\"." + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" msgstr "" -#: admin/forms.py:73 -msgid "Resize parameters must be choosen." +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" msgstr "" -#: admin/imageadmin.py:12 -msgid "Subject location" +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "Katalog o podanej nazwie już istnieje." + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "Filer" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "Biblioteka mediów" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "domyślny tekst alternatywny" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "domyślna etykieta" + +#: models/abstract.py:76 +msgid "subject location" msgstr "Współrzędne obiektu" -#: admin/imageadmin.py:13 -msgid "Location of the main subject of the scene." -msgstr "Współrzędne głownego obiektu prezentowanej sceny" +#: models/abstract.py:91 +msgid "image" +msgstr "obraz" -#: models/clipboardmodels.py:9 models/foldermodels.py:236 +#: models/abstract.py:92 +msgid "images" +msgstr "obrazy" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 msgid "user" msgstr "użytkownik" -#: models/clipboardmodels.py:11 models/filemodels.py:287 +#: models/clipboardmodels.py:17 models/filemodels.py:157 msgid "files" -msgstr "" +msgstr "pliki" -#: models/clipboardmodels.py:34 models/clipboardmodels.py:40 +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 msgid "clipboard" -msgstr "" +msgstr "schowek" -#: models/clipboardmodels.py:35 +#: models/clipboardmodels.py:25 msgid "clipboards" -msgstr "" +msgstr "schowki" -#: models/clipboardmodels.py:39 models/filemodels.py:35 -#: models/filemodels.py:286 +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 msgid "file" -msgstr "" +msgstr "plik" -#: models/clipboardmodels.py:44 +#: models/clipboardmodels.py:56 msgid "clipboard item" -msgstr "" +msgstr "element schowka" -#: models/clipboardmodels.py:45 +#: models/clipboardmodels.py:57 msgid "clipboard items" -msgstr "" +msgstr "elementy schowka" -#: models/filemodels.py:33 templates/admin/filer/folder/change_form.html:9 -#: templates/admin/filer/folder/directory_listing.html:74 +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 #: templates/admin/filer/folder/new_folder_form.html:4 -#: templates/admin/filer/tools/clipboard/clipboard.html:26 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 msgid "folder" msgstr "katalog" -#: models/filemodels.py:36 +#: models/filemodels.py:81 msgid "file size" -msgstr "" +msgstr "rozmiar pliku" -#: models/filemodels.py:38 +#: models/filemodels.py:87 msgid "sha1" -msgstr "" +msgstr "sha1" -#: models/filemodels.py:40 +#: models/filemodels.py:94 msgid "has all mandatory data" -msgstr "" +msgstr "posiada wszystkie potrzebne dane" -#: models/filemodels.py:42 +#: models/filemodels.py:100 msgid "original filename" -msgstr "" +msgstr "oryginalna nazwa pliku" -#: models/filemodels.py:44 models/foldermodels.py:99 +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 msgid "name" -msgstr "" +msgstr "nazwa" -#: models/filemodels.py:46 +#: models/filemodels.py:116 msgid "description" -msgstr "" +msgstr "opis" -#: models/filemodels.py:50 +#: models/filemodels.py:125 models/foldermodels.py:108 msgid "owner" -msgstr "" +msgstr "właściciel" -#: models/filemodels.py:52 models/foldermodels.py:105 +#: models/filemodels.py:129 models/foldermodels.py:116 msgid "uploaded at" -msgstr "" +msgstr "zaktualizowano" -#: models/filemodels.py:53 models/foldermodels.py:108 +#: models/filemodels.py:134 models/foldermodels.py:126 msgid "modified at" -msgstr "" +msgstr "zmieniono" -#: models/filemodels.py:57 +#: models/filemodels.py:140 msgid "Permissions disabled" +msgstr "Uprawnienia wyłączone" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." msgstr "" +"Wyłącz jakiekolwiek sprawdzanie uprawnień dla tego pliku. Plik będzie " +"dostępny publicznie dla wszystkich." -#: models/filemodels.py:58 -msgid "Disable any permission checking for this " +#: models/foldermodels.py:94 +msgid "parent" msgstr "" -#: models/foldermodels.py:107 +#: models/foldermodels.py:121 msgid "created at" -msgstr "" +msgstr "utworzono" -#: models/foldermodels.py:211 -#: templates/admin/filer/widgets/admin_folder.html:3 -#: templates/admin/filer/widgets/admin_folder.html:5 +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 msgid "Folder" -msgstr "" +msgstr "Katalog" -#: models/foldermodels.py:212 +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 msgid "Folders" msgstr "Katalogi" -#: models/foldermodels.py:227 +#: models/foldermodels.py:260 msgid "all items" msgstr "wszystkie elementy" -#: models/foldermodels.py:228 +#: models/foldermodels.py:261 msgid "this item only" -msgstr "tylko ten katalog" +msgstr "tylko ten element" -#: models/foldermodels.py:229 +#: models/foldermodels.py:262 msgid "this item and all children" msgstr "ten katalog i wszystkie podrzędne" -#: models/foldermodels.py:233 +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "zezwól" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "zabroń" + +#: models/foldermodels.py:280 msgid "type" msgstr "typ" -#: models/foldermodels.py:239 +#: models/foldermodels.py:297 msgid "group" msgstr "grupa" -#: models/foldermodels.py:240 +#: models/foldermodels.py:304 msgid "everybody" msgstr "wszyscy" -#: models/foldermodels.py:242 -msgid "can edit" -msgstr "może edytować" - -#: models/foldermodels.py:243 +#: models/foldermodels.py:309 msgid "can read" msgstr "może wyświetlić" -#: models/foldermodels.py:244 +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "może edytować" + +#: models/foldermodels.py:325 msgid "can add children" -msgstr "może dodawać el. podrzędne" +msgstr "może dodawać elementy podrzędne" -#: models/foldermodels.py:273 +#: models/foldermodels.py:333 msgid "folder permission" -msgstr "" +msgstr "uprawnienie katalogu" -#: models/foldermodels.py:274 +#: models/foldermodels.py:334 msgid "folder permissions" +msgstr "uprawnienia katalogu" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." msgstr "" -#: models/imagemodels.py:39 -msgid "date taken" -msgstr "Data wykonania" +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" -#: models/imagemodels.py:42 -msgid "default alt text" +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." msgstr "" -#: models/imagemodels.py:43 -msgid "default caption" +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." msgstr "" -#: models/imagemodels.py:45 templates/image_filer/image.html:6 -msgid "author" -msgstr "autor" +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "" -#: models/imagemodels.py:47 -msgid "must always publish author credit" +#: models/foldermodels.py:362 +msgid "Logical Path" msgstr "" -#: models/imagemodels.py:48 -msgid "must always publish copyright" +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" msgstr "" -#: models/imagemodels.py:50 -msgid "subject location" +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" msgstr "" -#: models/imagemodels.py:200 -msgid "image" +#: models/foldermodels.py:375 +msgid "Everybody" msgstr "" -#: models/imagemodels.py:201 -msgid "images" +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" msgstr "" -#: models/virtualitems.py:45 -#: templates/admin/filer/tools/clipboard/clipboard.html:26 -msgid "unfiled files" -msgstr "Luźne pliki" +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "data wykonania" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "autor" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "musi zawsze opublikować udział autora" -#: models/virtualitems.py:59 +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "musi zawsze opublikować prawa autorskie" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "szerokość w pikselach" + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "wysokość w pikselach" + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "opcje miniatur" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "Nieuporządkowane Przesłane" + +#: models/virtualitems.py:73 msgid "files with missing metadata" -msgstr "pliki z wybrakowanymi metadanymi" +msgstr "pliki z brakującymi metadanymi" -#: models/virtualitems.py:73 templates/admin/filer/breadcrumbs.html:6 -#: templates/admin/filer/folder/change_form.html:9 -#: templates/admin/filer/folder/directory_listing.html:74 -#: templates/image_filer/image_export_form.html:10 +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 msgid "root" msgstr "Katalog główny" -#: templates/admin/filer/actions.html:4 -msgid "Run the selected action" +#: settings.py:273 +msgid "Show table view" msgstr "" -#: templates/admin/filer/actions.html:4 -msgid "Go" +#: settings.py:278 +msgid "Show thumbnail view" msgstr "" -#: templates/admin/filer/actions.html:11 +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "Wykonaj wybraną akcję" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "Idź" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 msgid "Click here to select the objects across all pages" -msgstr "" +msgstr "Kliknij tutaj aby zaznaczyć obiekty na wszystkich stronach" -#: templates/admin/filer/actions.html:11 +#: templates/admin/filer/actions.html:14 #, python-format msgid "Select all %(total_count)s files and/or folders" -msgstr "" +msgstr "Zaznacz wszystkie %(total_count)s pliki i/lub katalogi" -#: templates/admin/filer/actions.html:13 +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 msgid "Clear selection" -msgstr "" +msgstr "Wyczyść zaznaczenie" #: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 msgid "Go back to admin homepage" msgstr "Wróć do panelu administracyjnego" #: templates/admin/filer/breadcrumbs.html:4 -#: templates/admin/filer/folder/change_form.html:7 -#: templates/image_filer/image_export_form.html:7 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 msgid "Home" msgstr "Początek" #: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 msgid "Go back to Filer app" msgstr "Wróć do aplikacji Filer" -#: templates/admin/filer/breadcrumbs.html:5 -#: templates/admin/filer/folder/change_form.html:8 -#: templates/image_filer/image_export_form.html:8 -msgid "Filer" -msgstr "Filer" - #: templates/admin/filer/breadcrumbs.html:6 -#: templates/image_filer/image_export_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:35 msgid "Go back to root folder" msgstr "Wróć do katalogu głównego" #: templates/admin/filer/breadcrumbs.html:8 -#: templates/admin/filer/breadcrumbs.html:11 -#: templates/admin/filer/folder/change_form.html:11 -#: templates/image_filer/image_export_form.html:12 -#: templates/image_filer/image_export_form.html:14 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 #, python-format msgid "Go back to '%(folder_name)s' folder" msgstr "Przejdź do katalogu '%(folder_name)s'" -#: templates/admin/filer/change_form.html:28 -msgid "duplicates" -msgstr "" - -#: templates/admin/filer/delete_confirmation.html:13 -#, python-format -msgid "" -"Deleting the %(object_name)s '%(escaped_object)s' would result in deleting " -"related objects, but your account doesn't have permission to delete the " -"following types of objects:" -msgstr "" - -#: templates/admin/filer/delete_confirmation.html:21 -#, python-format -msgid "" -"Deleting the %(object_name)s '%(escaped_object)s' would require deleting the " -"following protected related objects:" -msgstr "" - -#: templates/admin/filer/delete_confirmation.html:29 -#, python-format -msgid "" -"Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? " -"All of the following related items will be deleted:" -msgstr "" - -#: templates/admin/filer/delete_confirmation.html:34 -#: templates/admin/filer/delete_selected_files_confirmation.html:45 -msgid "Yes, I'm sure" -msgstr "" +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "Duplikaty" #: templates/admin/filer/delete_selected_files_confirmation.html:11 msgid "" @@ -489,402 +640,636 @@ msgid "" "objects, but your account doesn't have permission to delete the following " "types of objects:" msgstr "" +"Usunięcie zaznaczonych plików i/lub katalogów spowoduje usunięcie " +"powiązanych obiektów, niestety Twoje konto nie posiada uprawnień do " +"usunięcia następujących typów obiektów:" #: templates/admin/filer/delete_selected_files_confirmation.html:19 msgid "" "Deleting the selected files and/or folders would require deleting the " "following protected related objects:" msgstr "" +"Usunięcie zaznaczonych plików i/lub katalogów wymaga usunięcia następujących " +"chronionych obiektów powiązanych:" #: templates/admin/filer/delete_selected_files_confirmation.html:27 msgid "" "Are you sure you want to delete the selected files and/or folders? All of " "the following objects and their related items will be deleted:" msgstr "" +"Czy na pewno chcesz usunąć zaznaczone pliki i/lub katalogi? Następujące " +"obiekty oraz powiązane z nimi elementy zostaną usunięte:" -#: templates/admin/filer/folder/change_form.html:7 -#: templates/admin/filer/folder/change_form.html:8 -#: templates/admin/filer/folder/change_form.html:9 -#: templates/admin/filer/folder/directory_listing.html:74 -#: templates/image_filer/image_export_form.html:7 -#: templates/image_filer/image_export_form.html:8 -#: templates/image_filer/image_export_form.html:16 -msgid "Go back to" -msgstr "Wróć do" +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "Nie, wróć" -#: templates/admin/filer/folder/change_form.html:7 -#: templates/image_filer/image_export_form.html:7 -msgid "admin homepage" -msgstr "panelu administracyjnego" +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "Tak, na pewno" -#: templates/admin/filer/folder/change_form.html:22 -#: templates/admin/filer/image/change_form.html:9 +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 msgid "History" msgstr "Historia" +#: templates/admin/filer/file/change_form.html:37 #: templates/admin/filer/folder/change_form.html:23 -#: templates/admin/filer/image/change_form.html:10 +#: templates/admin/filer/image/change_form.html:37 msgid "View on site" msgstr "Zobacz na stronie" -#: templates/admin/filer/folder/change_form.html:35 -#: templates/admin/filer/folder/directory_listing.html:75 -#: templates/admin/filer/folder/directory_listing.html:85 -#: templates/admin/filer/folder/directory_table.html:23 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "Wróć do" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "panelu administracyjnego" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 msgid "Folder Icon" msgstr "Ikona katalogu" -#: templates/admin/filer/folder/choose_copy_destination.html:12 +#: templates/admin/filer/folder/choose_copy_destination.html:23 msgid "" "Your account doesn't have permissions to copy all of the selected files and/" "or folders." msgstr "" +"Twoje konto nie ma uprawnień do skopiowania wszystkich zaznaczonych plików i/" +"lub katalogów." -#: templates/admin/filer/folder/choose_copy_destination.html:15 -#: templates/admin/filer/folder/choose_move_destination.html:15 +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "Powróć" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 msgid "There are no destination folders available." -msgstr "" +msgstr "Brak dostępnych katalogów docelowych." -#: templates/admin/filer/folder/choose_copy_destination.html:18 +#: templates/admin/filer/folder/choose_copy_destination.html:35 msgid "There are no files and/or folders available to copy." -msgstr "" +msgstr "Brak dostępnych plików i/lub katalogów do skopiowania." -#: templates/admin/filer/folder/choose_copy_destination.html:20 +#: templates/admin/filer/folder/choose_copy_destination.html:40 msgid "" "The following files and/or folders will be copied to a destination folder " "(retaining their tree structure):" msgstr "" +"Następujące pliki i/lub katalogi zostaną skopiowane do katalogu docelowego " +"(z zachowaniem ich struktury):" -#: templates/admin/filer/folder/choose_copy_destination.html:32 -#: templates/admin/filer/folder/choose_move_destination.html:32 +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 msgid "Destination folder:" -msgstr "" +msgstr "Katalog docelowy:" -#: templates/admin/filer/folder/choose_copy_destination.html:39 +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 msgid "Copy" -msgstr "" +msgstr "Skopiuj" -#: templates/admin/filer/folder/choose_images_resize_options.html:12 +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "Nie można kopiować plików to tego samego folderu" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 msgid "" "Your account doesn't have permissions to resize all of the selected images." msgstr "" +"Twoje konto nie ma uprawnień do zmiany rozmiaru wszystkich zaznaczonych " +"obrazów." -#: templates/admin/filer/folder/choose_images_resize_options.html:15 +#: templates/admin/filer/folder/choose_images_resize_options.html:18 msgid "There are no images available to resize." -msgstr "" +msgstr "Brak dostępnych obrazów do zmiany ich rozmiaru." -#: templates/admin/filer/folder/choose_images_resize_options.html:17 +#: templates/admin/filer/folder/choose_images_resize_options.html:20 msgid "The following images will be resized:" -msgstr "" - -#: templates/admin/filer/folder/choose_images_resize_options.html:30 -msgid "Choose an existing thumbnail option or enter resize parameters:" -msgstr "" +msgstr "Następujące obrazy będą miały zmieniony rozmiar:" #: templates/admin/filer/folder/choose_images_resize_options.html:32 -msgid "Choose resize parameters:" +msgid "Choose an existing thumbnail option or enter resize parameters:" msgstr "" +"Wybierz istniejącą opcje miniatury albo wprowadź parametry zmiany rozmiaru:" -#: templates/admin/filer/folder/choose_images_resize_options.html:35 +#: templates/admin/filer/folder/choose_images_resize_options.html:36 msgid "" "Warning: Images will be resized in-place and originals will be lost. Maybe " "first make a copy of them to retain the originals." msgstr "" +"Uwaga: Rozmiary obrazów zostanie zmienione w miejscu a oryginały zostaną " +"utracone. W celu zachowania oryginałów, najpierw wykonaj ich kopię." -#: templates/admin/filer/folder/choose_images_resize_options.html:36 +#: templates/admin/filer/folder/choose_images_resize_options.html:39 msgid "Resize" -msgstr "" +msgstr "Zmień rozmiar" -#: templates/admin/filer/folder/choose_move_destination.html:12 +#: templates/admin/filer/folder/choose_move_destination.html:35 msgid "" "Your account doesn't have permissions to move all of the selected files and/" "or folders." msgstr "" +"Twoje konto nie ma uprawnień do przeniesienia wszystkich zaznaczonych plików " +"i/lub katalogów." -#: templates/admin/filer/folder/choose_move_destination.html:18 +#: templates/admin/filer/folder/choose_move_destination.html:47 msgid "There are no files and/or folders available to move." -msgstr "" +msgstr "Brak plików i/lub folderów do przeniesienia." -#: templates/admin/filer/folder/choose_move_destination.html:20 +#: templates/admin/filer/folder/choose_move_destination.html:52 msgid "" "The following files and/or folders will be moved to a destination folder " "(retaining their tree structure):" msgstr "" +"Następujące pliki i/lub katalogi zostaną przeniesione do katalogu docelowego " +"(z zachowaniem ich struktury):" -#: templates/admin/filer/folder/choose_move_destination.html:38 +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 msgid "Move" -msgstr "" +msgstr "Przenieś" -#: templates/admin/filer/folder/choose_rename_format.html:12 +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "Nie można przenieść plików do tego samego folderu" + +#: templates/admin/filer/folder/choose_rename_format.html:15 msgid "" "Your account doesn't have permissions to rename all of the selected files." msgstr "" +"Twoje konto nie posiada uprawnień do zmiany nazwy wszystkich zaznaczonych " +"plików." -#: templates/admin/filer/folder/choose_rename_format.html:15 +#: templates/admin/filer/folder/choose_rename_format.html:18 msgid "There are no files available to rename." -msgstr "" +msgstr "Brak dostępnych plików do zmiany nazwy." -#: templates/admin/filer/folder/choose_rename_format.html:17 +#: templates/admin/filer/folder/choose_rename_format.html:20 msgid "" "The following files will be renamed (they will stay in their folders and " "keep original filename, only displayed filename will be changed):" msgstr "" +"Następujące pliki będą miały zmienioną nazwę (pliki pozostaną w swoich " +"katalogach i zachowają oryginalne nazwy, zmieni się jedynie ich wyświetlana " +"nazwa):" -#: templates/admin/filer/folder/choose_rename_format.html:54 +#: templates/admin/filer/folder/choose_rename_format.html:59 msgid "Rename" -msgstr "" +msgstr "Zmień nazwę" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "Wróć do katalogu nadrzędnego" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "Zmień dane aktualnie wyświetlanego katalogu" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "Zmień" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "Kliknij tutaj aby szukać daną frazę" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "Szukaj" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "Zamknij" -#: templates/admin/filer/folder/directory_listing.html:66 +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "Limit" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "Zaznacz, by ograniczyć szukanie do bieżącego folderu" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "Ogranicz szukanie do bieżącego folderu" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "Usuń" + +#: templates/admin/filer/folder/directory_listing.html:203 msgid "Adds a new Folder" msgstr "Dodaje nowy katalog" -#: templates/admin/filer/folder/directory_listing.html:66 -#: templates/image_filer/include/export_dialog.html:34 +#: templates/admin/filer/folder/directory_listing.html:206 msgid "New Folder" msgstr "Nowy katalog" -#: templates/admin/filer/folder/directory_listing.html:67 -msgid "upload files" -msgstr "" +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "Wyślij Pliki" -#: templates/admin/filer/folder/directory_listing.html:67 -msgid "Upload" -msgstr "" +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "Musisz najpierw wybrać katalog" -#: templates/admin/filer/folder/directory_listing.html:74 -msgid "Go back to the parent folder" -msgstr "Wróć do katalogu nadrzędnego" +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "Nazwa" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "Właściciel" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "Rozmiar" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "Akcja" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "Zmień dane katalogu '%(item_label)s'" -#: templates/admin/filer/folder/directory_listing.html:76 -#: templates/admin/filer/folder/directory_table.html:29 -#: templates/admin/filer/tools/search_form.html:18 +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 #, python-format -msgid "1 folder" +msgid "%(counter)s folder" msgid_plural "%(counter)s folders" msgstr[0] "%(counter)s katalog" msgstr[1] "%(counter)s katalogi" msgstr[2] "%(counter)s katalogów" +msgstr[3] "%(counter)s katalogów" -#: templates/admin/filer/folder/directory_listing.html:76 -#: templates/admin/filer/folder/directory_table.html:29 -#: templates/admin/filer/tools/search_form.html:19 +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 #, python-format -msgid "1 file" +msgid "%(counter)s file" msgid_plural "%(counter)s files" msgstr[0] "%(counter)s plik" msgstr[1] "%(counter)s pliki" msgstr[2] "%(counter)s plików" +msgstr[3] "%(counter)s plików" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "Zmień dane katalogu" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "Usuń katalog" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "Wybierz ten plik" -#: templates/admin/filer/folder/directory_listing.html:80 -msgid "Change current folder details" -msgstr "Zmodyfikuj dane aktualnie wyświetlanego katalogu" - -#: templates/admin/filer/folder/directory_listing.html:80 -#: templates/admin/filer/folder/directory_table.html:27 -#: templates/admin/filer/folder/directory_table.html:43 -msgid "Change" -msgstr "Zmień" +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "Zmień dane '%(item_label)s'" -#: templates/admin/filer/folder/directory_table.html:13 -msgid "Name" -msgstr "Nazwa" +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "Uprawnienia" -#: templates/admin/filer/folder/directory_table.html:23 -#: templates/admin/filer/folder/directory_table.html:27 -#: templates/admin/filer/folder/directory_table.html:29 -#, python-format -msgid "Change '%(item_label)s' folder details" -msgstr "Zmodyfikuj dane katalogu '%(item_label)s'" +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "wyłączony" -#: templates/admin/filer/folder/directory_table.html:30 -#: templates/admin/filer/folder/directory_table.html:45 -msgid "Owner" -msgstr "Właściciel" +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "włączony" -#: templates/admin/filer/folder/directory_table.html:37 -msgid "Select this file" -msgstr "Wybierz ten plik" +#: templates/admin/filer/folder/directory_table_list.html:144 +#, fuzzy +#| msgid "Move selected files to clipboard" +msgid "URL copied to clipboard" +msgstr "Przenieś zaznaczone pliki do schowka" -#: templates/admin/filer/folder/directory_table.html:39 -#: templates/admin/filer/folder/directory_table.html:43 -#: templates/admin/filer/folder/directory_table.html:44 +#: templates/admin/filer/folder/directory_table_list.html:147 #, python-format -msgid "Change '%(item_label)s' details" -msgstr "Zmodyfikuj dane '%(item_label)s'" +msgid "Canonical url '%(item_label)s'" +msgstr "Kanoniczny url '%(item_label)s'" -#: templates/admin/filer/folder/directory_table.html:42 +#: templates/admin/filer/folder/directory_table_list.html:151 #, python-format -msgid "Delete '%(item_label)s'" -msgstr "" +msgid "Download '%(item_label)s'" +msgstr "Pobierz '%(item_label)s'" -#: templates/admin/filer/folder/directory_table.html:42 -msgid "Delete" -msgstr "" +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "Usuń plik" -#: templates/admin/filer/folder/directory_table.html:46 -msgid "Permissions" -msgstr "" +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "Upuść pliki tutaj lub kliknij na przycisk \"Wyślij Pliki\" " -#: templates/admin/filer/folder/directory_table.html:46 -msgid "disabled" -msgstr "" +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "Upuść plik by wysłać go do:" -#: templates/admin/filer/folder/directory_table.html:46 -msgid "enabled" -msgstr "" +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "Upload" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "anuluj" -#: templates/admin/filer/folder/directory_table.html:50 -msgid "Move to clipboard" -msgstr "Przenieś do schowka" +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "Wysłano pomyślnie!" -#: templates/admin/filer/folder/directory_table.html:58 -msgid "there are no files or subfolders" -msgstr "Nie dodano tutaj jeszcze żadnych plików, bądź katalogów" +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "Wysyłanie anulowane!" -#: templates/admin/filer/folder/directory_table.html:65 +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 msgid "previous" -msgstr "" +msgstr "poprzedni" -#: templates/admin/filer/folder/directory_table.html:69 +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 #, python-format -msgid "" -"\n" -" Page %(number)s of %(num_pages)s.\n" -" " -msgstr "" +msgid "Page %(number)s of %(num_pages)s." +msgstr "Strona %(number)s z %(num_pages)s." -#: templates/admin/filer/folder/directory_table.html:75 +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 msgid "next" +msgstr "następny" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "Wybierz wszystkie %(total_count)s" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" msgstr "" #: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 msgid "Add new" msgstr "Dodaj nowy" -#: templates/admin/filer/folder/new_folder_form.html:13 +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:15 msgid "Please correct the error below." msgid_plural "Please correct the errors below." -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Proszę naprawić poniższy błąd." +msgstr[1] "Proszę naprawić poniższe błędy." +msgstr[2] "Proszę naprawić poniższe błędy." +msgstr[3] "Proszę naprawić poniższe błędy." -#: templates/admin/filer/folder/new_folder_form.html:28 +#: templates/admin/filer/folder/new_folder_form.html:30 msgid "Save" msgstr "Zapisz" -#: templates/admin/filer/image/change_form.html:21 -msgid "Full size preview" -msgstr "Pełnowymiarowy podgląd" +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" -#: templates/admin/filer/tools/search_form.html:8 -#: templates/admin/filer/tools/search_form.html:14 -msgid "Search" -msgstr "Szukaj" +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "Schowek" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "Wklej tutaj wszystkie elementy" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "Przenieś wszystkie elementy schowka do" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "Wyczyść Schowek" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "schowek jest pusty" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "Nie udało się przesłać pliku" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" -#: templates/admin/filer/tools/search_form.html:13 -msgid "Enter your search phrase here" -msgstr "Wprowadź kryteria wyszukiwania" +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" -#: templates/admin/filer/tools/search_form.html:14 -msgid "Click here to" -msgstr "Kliknij tutaj by" +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" -#: templates/admin/filer/tools/search_form.html:14 -msgid "run search for entered phrase" -msgstr "wyszukaj wprowadzoną frazę" +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "Typ" -#: templates/admin/filer/tools/search_form.html:15 -msgid "Check it to" -msgstr "Zaznacz by" +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "Rozmiar pliku" -#: templates/admin/filer/tools/search_form.html:15 -#: templates/admin/filer/tools/search_form.html:16 -msgid "limit the search to current folder" -msgstr "wyszukaj tylko w tym katalogu" +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "Modyfikowano" -#: templates/admin/filer/tools/search_form.html:18 +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "Utworzono" + +#: templates/admin/filer/tools/search_form.html:5 msgid "found" msgstr "znaleziono" -#: templates/admin/filer/tools/search_form.html:18 +#: templates/admin/filer/tools/search_form.html:5 msgid "and" msgstr "i" -#: templates/admin/filer/tools/search_form.html:19 +#: templates/admin/filer/tools/search_form.html:7 msgid "cancel search" msgstr "anuluj wyszukiwanie" -#: templates/admin/filer/tools/upload_button_js.html:24 -#: templates/admin/filer/widgets/admin_file.html:7 -#: templates/admin/filer/widgets/admin_file.html:8 -msgid "file missing" -msgstr "" +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "Usuń" -#: templates/admin/filer/tools/clipboard/clipboard.html:7 -msgid "Clipboard" -msgstr "Schowek" +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "lub upuść swój plik tutaj" -#: templates/admin/filer/tools/clipboard/clipboard.html:19 -msgid "Paste all items here" -msgstr "Wklej tutaj wszystkie elementy" +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "brak zaznaczonych plików" -#: templates/admin/filer/tools/clipboard/clipboard.html:26 -msgid "discard" -msgstr "odrzuć" +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "Wyszukaj" -#: templates/admin/filer/tools/clipboard/clipboard.html:26 -msgid "Move all clipboard files to" -msgstr "Przenieś wszystkie el. schowka do" +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "Wybierz plik" -#: templates/admin/filer/tools/clipboard/clipboard.html:43 -msgid "the clipboard is empty" -msgstr "schowek jest pusty" +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" -#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:11 -msgid "upload failed" -msgstr "Nie udało się przesłać pliku" +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" -#: templates/admin/filer/widgets/admin_file.html:11 -msgid "no file selected" +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" msgstr "" -#: templates/admin/filer/widgets/admin_file.html:14 -#: templates/admin/filer/widgets/admin_file.html:15 -#: templates/admin/filer/widgets/admin_folder.html:7 -#: templates/admin/filer/widgets/admin_folder.html:8 -msgid "Lookup" -msgstr "Wyszukaj" +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" -#: templates/admin/filer/widgets/admin_file.html:17 -#: templates/admin/filer/widgets/admin_folder.html:10 -msgid "Clear" -msgstr "Usuń" +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" -#: templates/admin/filer/widgets/admin_folder.html:5 -msgid "none selected" +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" msgstr "" -#: templates/image_filer/folder.html:3 -#, python-format -msgid "Folder '%(folder_label)s' files" -msgstr "Pliki w katalogu '%(folder_label)s' " +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" -#: templates/image_filer/folder.html:6 -msgid "File name" -msgstr "Nazwa pliku" +#~ msgid "none selected" +#~ msgstr "none selected" -#: templates/image_filer/image_export_form.html:17 -msgid "export" -msgstr "eksport" +#~ msgid "Add Folder" +#~ msgstr "Add Folder" -#: templates/image_filer/image_export_form.html:27 -msgid "download image" -msgstr "pobierz obrazek" +#~ msgid "Subject Location" +#~ msgstr "Subject location" -#: templates/image_filer/include/export_dialog.html:13 -msgid "Folder name already taken." -msgstr "Katalog o podanej nazwie juz istnieje" +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" +#~ msgstr[2] "15c0f2d28d6dab1af1f6d94906beb627_pl_2" +#~ msgstr[3] "15c0f2d28d6dab1af1f6d94906beb627_pl_3" -#: templates/image_filer/include/export_dialog.html:15 -msgid "Submit" -msgstr "Wyślij" +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/pt/LC_MESSAGES/django.mo b/filer/locale/pt/LC_MESSAGES/django.mo new file mode 100644 index 000000000..6a145895c Binary files /dev/null and b/filer/locale/pt/LC_MESSAGES/django.mo differ diff --git a/filer/locale/pt/LC_MESSAGES/django.po b/filer/locale/pt/LC_MESSAGES/django.po new file mode 100644 index 000000000..78553fbd5 --- /dev/null +++ b/filer/locale/pt/LC_MESSAGES/django.po @@ -0,0 +1,1230 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Angelo Dini \n" +"Language-Team: Portuguese (http://app.transifex.com/divio/django-filer/" +"language/pt/)\n" +"Language: pt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % " +"1000000 == 0 ? 1 : 2;\n" + +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "" + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "" + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "" + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "" + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "" + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "" + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "" + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "" + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "" + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "" + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "" + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "" + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "" + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "" + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "" + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "" + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "" + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "" + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "" + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "" + +#: models/abstract.py:91 +msgid "image" +msgstr "" + +#: models/abstract.py:92 +msgid "images" +msgstr "" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "" + +#: models/filemodels.py:116 +msgid "description" +msgstr "" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "" + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "" + +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:144 +msgid "URL copied to clipboard" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "" + +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" +#~ msgstr[2] "15c0f2d28d6dab1af1f6d94906beb627_pl_2" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/pt_BR/LC_MESSAGES/django.mo b/filer/locale/pt_BR/LC_MESSAGES/django.mo index c65986b60..423ed55ba 100644 Binary files a/filer/locale/pt_BR/LC_MESSAGES/django.mo and b/filer/locale/pt_BR/LC_MESSAGES/django.mo differ diff --git a/filer/locale/pt_BR/LC_MESSAGES/django.po b/filer/locale/pt_BR/LC_MESSAGES/django.po index 755a254d1..220c55c5c 100644 --- a/filer/locale/pt_BR/LC_MESSAGES/django.po +++ b/filer/locale/pt_BR/LC_MESSAGES/django.po @@ -3,482 +3,638 @@ # This file is distributed under the same license as the PACKAGE package. # # Translators: +# Translators: +# Translators: +# Claudio Rogerio Carvalho Filho , 2017 +# Julio Lucchese , 2018 +# Rodrigo , 2013 msgid "" msgstr "" -"Project-Id-Version: django-filer\n" +"Project-Id-Version: django Filer\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-07-13 19:10+0200\n" -"PO-Revision-Date: 2012-09-03 20:12+0100\n" -"Last-Translator: Stefan Foulis \n" -"Language-Team: LANGUAGE \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Julio Lucchese , 2018\n" +"Language-Team: Portuguese (Brazil) (http://app.transifex.com/divio/django-" +"filer/language/pt_BR/)\n" +"Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Language: pt_BR\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % " +"1000000 == 0 ? 1 : 2;\n" -#: views.py:103 -msgid "Folder with this name already exists." +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." msgstr "" -#: admin/fileadmin.py:41 +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 msgid "Advanced" msgstr "Avançado" -#: admin/folderadmin.py:324 admin/folderadmin.py:427 +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "URL canônico" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 msgid "" "Items must be selected in order to perform actions on them. No items have " "been changed." msgstr "" +"itens precisam ser selecionar para que a ação seja executada. Nenhuma " +"alteração foi efetuada." -#: admin/folderadmin.py:344 +#: admin/folderadmin.py:434 #, python-format msgid "%(total_count)s selected" msgid_plural "All %(total_count)s selected" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%(total_count)s selecionado" +msgstr[1] "Todos %(total_count)s selecionados" +msgstr[2] "Todos %(total_count)s selecionados" -#: admin/folderadmin.py:377 +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "Listando diretório para %(folder_name)s" + +#: admin/folderadmin.py:475 #, python-format msgid "0 of %(cnt)s selected" -msgstr "" +msgstr "0 de %(cnt)s selecionados" -#: admin/folderadmin.py:456 +#: admin/folderadmin.py:612 msgid "No action selected." -msgstr "" +msgstr "Nenhuma ação selecionada." -#: admin/folderadmin.py:497 +#: admin/folderadmin.py:664 #, python-format msgid "Successfully moved %(count)d files to clipboard." -msgstr "" +msgstr "%(count)d arquivo(s) movidos para a área de transferência com sucesso." -#: admin/folderadmin.py:503 +#: admin/folderadmin.py:669 msgid "Move selected files to clipboard" -msgstr "" +msgstr "Mover os arquivos selecionados para a área de transferência" -#: admin/folderadmin.py:537 +#: admin/folderadmin.py:709 #, python-format msgid "Successfully disabled permissions for %(count)d files." -msgstr "" +msgstr "%(count)d arquivo(s) tiveram suas permissões desativadas com sucesso." -#: admin/folderadmin.py:541 +#: admin/folderadmin.py:711 #, python-format msgid "Successfully enabled permissions for %(count)d files." -msgstr "" +msgstr "%(count)d arquivo(s) tiveram suas permissões ativadas com sucesso." -#: admin/folderadmin.py:550 +#: admin/folderadmin.py:719 msgid "Enable permissions for selected files" -msgstr "" +msgstr "Habilitar as permissões para os arquivos selecionados" -#: admin/folderadmin.py:555 +#: admin/folderadmin.py:725 msgid "Disable permissions for selected files" -msgstr "" +msgstr "Desabilitar as permissões para os arquivos selecionados" -#: admin/folderadmin.py:623 +#: admin/folderadmin.py:789 #, python-format msgid "Successfully deleted %(count)d files and/or folders." -msgstr "" +msgstr "%(count)d arquivo(s) e/ou pasta(s) foram removidos com sucesso." -#: admin/folderadmin.py:630 +#: admin/folderadmin.py:794 msgid "Cannot delete files and/or folders" -msgstr "" +msgstr "Não é possível remover arquivo(s) e/ou pasta(s)" -#: admin/folderadmin.py:632 +#: admin/folderadmin.py:796 msgid "Are you sure?" -msgstr "" +msgstr "Você tem certeza?" -#: admin/folderadmin.py:637 +#: admin/folderadmin.py:802 msgid "Delete files and/or folders" -msgstr "" +msgstr "Remover arquivo(s) e/ou pasta(s)" -#: admin/folderadmin.py:656 +#: admin/folderadmin.py:823 msgid "Delete selected files and/or folders" -msgstr "" +msgstr "Remover arquivo(s) e/ou pasta(s) selecionados" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "Pastas com os nomes %s s já existem no local selecionado" -#: admin/folderadmin.py:771 +#: admin/folderadmin.py:934 #, python-format msgid "" "Successfully moved %(count)d files and/or folders to folder " "'%(destination)s'." msgstr "" +"%(count)d arquivo(s) e/ou pasta(s) foram movidos para a pasta " +"'%(destination)s' com sucesso." -#: admin/folderadmin.py:778 admin/folderadmin.py:780 +#: admin/folderadmin.py:942 admin/folderadmin.py:944 msgid "Move files and/or folders" -msgstr "" +msgstr "Mover arquivo(s) e/ou pasta(s)" -#: admin/folderadmin.py:797 +#: admin/folderadmin.py:959 msgid "Move selected files and/or folders" -msgstr "" +msgstr "Mover arquivo(s) e/ou pasta(s) selecionados" -#: admin/folderadmin.py:854 +#: admin/folderadmin.py:1016 #, python-format msgid "Successfully renamed %(count)d files." -msgstr "" +msgstr "%(count)d arquivo(s) foram renomeados com sucesso." -#: admin/folderadmin.py:862 admin/folderadmin.py:864 admin/folderadmin.py:881 +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 msgid "Rename files" -msgstr "" +msgstr "Renomear arquivos" -#: admin/folderadmin.py:975 +#: admin/folderadmin.py:1137 #, python-format msgid "" "Successfully copied %(count)d files and/or folders to folder " "'%(destination)s'." msgstr "" +"%(count)d arquivo(s) e/ou pasta(s) foram copiados para o pasta " +"'%(destination)s' com sucesso." -#: admin/folderadmin.py:989 admin/folderadmin.py:991 +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 msgid "Copy files and/or folders" -msgstr "" +msgstr "Copiar arquivo(s) e/ou pasta(s)" -#: admin/folderadmin.py:1010 +#: admin/folderadmin.py:1174 msgid "Copy selected files and/or folders" -msgstr "" +msgstr "Copiar arquivo(s) e/ou pasta(s) selecionados" -#: admin/folderadmin.py:1105 +#: admin/folderadmin.py:1279 #, python-format msgid "Successfully resized %(count)d images." -msgstr "" +msgstr "%(count)d imagem(ens) tiveram seu tamanho alterado com sucesso." -#: admin/folderadmin.py:1113 admin/folderadmin.py:1115 +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 msgid "Resize images" -msgstr "" +msgstr "Redimensionar imagens" -#: admin/folderadmin.py:1133 +#: admin/folderadmin.py:1303 msgid "Resize selected images" -msgstr "" +msgstr "Redimensionar imagens selecionadas" -#: admin/forms.py:26 +#: admin/forms.py:24 msgid "Suffix which will be appended to filenames of copied files." -msgstr "" +msgstr "Sufixo que será anexado aos nomes dos arquivos copiados" -#: admin/forms.py:33 +#: admin/forms.py:31 #, python-format msgid "" "Suffix should be a valid, simple and lowercase filename part, like " "\"%(valid)s\"." msgstr "" +"O sufixo precisa ser válido, simples e com letras minúsculas para o nome de " +"um arquivo, como por exemplo: \"%(valid)s\"." -#: admin/forms.py:54 +#: admin/forms.py:52 #, python-format msgid "Unknown rename format value key \"%(key)s\"." msgstr "" +"A chave de valor \"%(key)s\" utilizada para renomear o arquivo é " +"desconhecida." -#: admin/forms.py:56 +#: admin/forms.py:54 #, python-format msgid "Invalid rename format: %(error)s." -msgstr "" +msgstr "Formato inválido para renomear: %(error)s." -#: admin/forms.py:62 +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 msgid "thumbnail option" -msgstr "" +msgstr "opções de miniaturas" -#: admin/forms.py:63 +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 msgid "width" -msgstr "" +msgstr "largura" -#: admin/forms.py:64 +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 msgid "height" -msgstr "" +msgstr "altura" -#: admin/forms.py:65 +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 msgid "crop" -msgstr "" +msgstr "recortar" -#: admin/forms.py:66 +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 msgid "upscale" -msgstr "" +msgstr "aumentar" -#: admin/forms.py:71 +#: admin/forms.py:79 msgid "Thumbnail option or resize parameters must be choosen." msgstr "" +"Escolher entre as opções de miniaturas ou parâmetros de redimensionamento." + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "Local do assunto" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "Localização do tema principal da cena. Formato: \"x, y\"." -#: admin/forms.py:73 -msgid "Resize parameters must be choosen." +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "Formato de localização de assunto inválido." + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "A localização do assunto está fora da imagem." + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "Sua entrada: \"{subject_location}\". " + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" msgstr "" -#: admin/imageadmin.py:12 -msgid "Subject location" -msgstr "Local de Assunto" +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" -#: admin/imageadmin.py:13 -msgid "Location of the main subject of the scene." -msgstr "Localização do assunto principal da cena." +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "Já existe uma pasta com esse nome." + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "Filer" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "Biblioteca de Mídia" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "alt text padrão" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "caption padrão" -#: models/clipboardmodels.py:9 models/foldermodels.py:236 +#: models/abstract.py:76 +msgid "subject location" +msgstr "local do assunto" + +#: models/abstract.py:91 +msgid "image" +msgstr "imagem" + +#: models/abstract.py:92 +msgid "images" +msgstr "imagens" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 msgid "user" msgstr "usuário" -#: models/clipboardmodels.py:11 models/filemodels.py:287 +#: models/clipboardmodels.py:17 models/filemodels.py:157 msgid "files" msgstr "arquivos" -#: models/clipboardmodels.py:34 models/clipboardmodels.py:40 +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 msgid "clipboard" msgstr "Área de transferência" -#: models/clipboardmodels.py:35 +#: models/clipboardmodels.py:25 msgid "clipboards" -msgstr "Área de transferência" +msgstr "áreas de transferência" -#: models/clipboardmodels.py:39 models/filemodels.py:35 -#: models/filemodels.py:286 +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 msgid "file" msgstr "arquivo" -#: models/clipboardmodels.py:44 +#: models/clipboardmodels.py:56 msgid "clipboard item" msgstr "item da área de transferência" -#: models/clipboardmodels.py:45 +#: models/clipboardmodels.py:57 msgid "clipboard items" msgstr "itens da área de transferência" -#: models/filemodels.py:33 templates/admin/filer/folder/change_form.html:9 -#: templates/admin/filer/folder/directory_listing.html:74 +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 #: templates/admin/filer/folder/new_folder_form.html:4 -#: templates/admin/filer/tools/clipboard/clipboard.html:26 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 msgid "folder" msgstr "pasta" -#: models/filemodels.py:36 +#: models/filemodels.py:81 msgid "file size" -msgstr "" +msgstr "tamanho do arquivo" -#: models/filemodels.py:38 +#: models/filemodels.py:87 msgid "sha1" -msgstr "" +msgstr "sha1" -#: models/filemodels.py:40 +#: models/filemodels.py:94 msgid "has all mandatory data" -msgstr "" +msgstr "possui todos os dados necessários" -#: models/filemodels.py:42 +#: models/filemodels.py:100 msgid "original filename" -msgstr "" +msgstr "nome original do arquivo" -#: models/filemodels.py:44 models/foldermodels.py:99 +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 msgid "name" msgstr "nome" -#: models/filemodels.py:46 +#: models/filemodels.py:116 msgid "description" msgstr "descrição" -#: models/filemodels.py:50 +#: models/filemodels.py:125 models/foldermodels.py:108 msgid "owner" msgstr "Proprietário" -#: models/filemodels.py:52 models/foldermodels.py:105 +#: models/filemodels.py:129 models/foldermodels.py:116 msgid "uploaded at" -msgstr "" +msgstr "enviado em" -#: models/filemodels.py:53 models/foldermodels.py:108 +#: models/filemodels.py:134 models/foldermodels.py:126 msgid "modified at" -msgstr "" +msgstr "modificado em" -#: models/filemodels.py:57 +#: models/filemodels.py:140 msgid "Permissions disabled" msgstr "Permissões desabilitadas" -#: models/filemodels.py:58 -msgid "Disable any permission checking for this " -msgstr "Desative qualquer verificação de permissão para este" +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" +"Desative qualquer verificação de permissão para este arquivo. O arquivo " +"estará acessível ao público para que qualquer possa acessar." -#: models/foldermodels.py:107 -msgid "created at" +#: models/foldermodels.py:94 +msgid "parent" msgstr "" -#: models/foldermodels.py:211 -#: templates/admin/filer/widgets/admin_folder.html:3 -#: templates/admin/filer/widgets/admin_folder.html:5 +#: models/foldermodels.py:121 +msgid "created at" +msgstr "criado em" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 msgid "Folder" msgstr "Pasta" -#: models/foldermodels.py:212 +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 msgid "Folders" msgstr "Pastas" -#: models/foldermodels.py:227 +#: models/foldermodels.py:260 msgid "all items" msgstr "todos os itens" -#: models/foldermodels.py:228 +#: models/foldermodels.py:261 msgid "this item only" msgstr "este item somente" -#: models/foldermodels.py:229 +#: models/foldermodels.py:262 msgid "this item and all children" -msgstr "este item e todas subjacentes" +msgstr "este item e todos subjacentes" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "permitir" -#: models/foldermodels.py:233 +#: models/foldermodels.py:268 +msgid "deny" +msgstr "negar" + +#: models/foldermodels.py:280 msgid "type" msgstr "tipo" -#: models/foldermodels.py:239 +#: models/foldermodels.py:297 msgid "group" msgstr "grupo" -#: models/foldermodels.py:240 +#: models/foldermodels.py:304 msgid "everybody" msgstr "todos" -#: models/foldermodels.py:242 -msgid "can edit" -msgstr "pode editar" - -#: models/foldermodels.py:243 +#: models/foldermodels.py:309 msgid "can read" msgstr "pode ler" -#: models/foldermodels.py:244 +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "pode editar" + +#: models/foldermodels.py:325 msgid "can add children" msgstr "pode adicionar filhos" -#: models/foldermodels.py:273 +#: models/foldermodels.py:333 msgid "folder permission" msgstr "permissão de pasta" -#: models/foldermodels.py:274 +#: models/foldermodels.py:334 msgid "folder permissions" msgstr "permissões de pasta" -#: models/imagemodels.py:39 -msgid "date taken" -msgstr "data de tomada" +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" -#: models/imagemodels.py:42 -msgid "default alt text" +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." msgstr "" -#: models/imagemodels.py:43 -msgid "default caption" +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." msgstr "" -#: models/imagemodels.py:45 templates/image_filer/image.html:6 -msgid "author" -msgstr "autor" +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" -#: models/imagemodels.py:47 -msgid "must always publish author credit" +#: models/foldermodels.py:360 +msgid "All Folders" msgstr "" -#: models/imagemodels.py:48 -msgid "must always publish copyright" +#: models/foldermodels.py:362 +msgid "Logical Path" msgstr "" -#: models/imagemodels.py:50 -msgid "subject location" +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" msgstr "" -#: models/imagemodels.py:200 -msgid "image" -msgstr "imagem" +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" -#: models/imagemodels.py:201 -msgid "images" -msgstr "imagens" +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" -#: models/virtualitems.py:45 -#: templates/admin/filer/tools/clipboard/clipboard.html:26 -msgid "unfiled files" -msgstr "arquivos unfiled" +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "" -#: models/virtualitems.py:59 +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "data de tomada" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "autor" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "necessário sempre publicar os créditos do autor" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "necessário sempre publicar os direitos autorais" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "largura em pixel." + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "altura em pixel." + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "opções de miniaturas" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "Uploads não classificados" + +#: models/virtualitems.py:73 msgid "files with missing metadata" msgstr "arquivos com falta de metadados" -#: models/virtualitems.py:73 templates/admin/filer/breadcrumbs.html:6 -#: templates/admin/filer/folder/change_form.html:9 -#: templates/admin/filer/folder/directory_listing.html:74 -#: templates/image_filer/image_export_form.html:10 +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 msgid "root" msgstr "raiz" -#: templates/admin/filer/actions.html:4 -msgid "Run the selected action" +#: settings.py:273 +msgid "Show table view" msgstr "" -#: templates/admin/filer/actions.html:4 -msgid "Go" +#: settings.py:278 +msgid "Show thumbnail view" msgstr "" -#: templates/admin/filer/actions.html:11 +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "Executar a ação selecionada" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "Avançar" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 msgid "Click here to select the objects across all pages" -msgstr "" +msgstr "Clique aqui para selecionar os objetos em todas as páginas" -#: templates/admin/filer/actions.html:11 +#: templates/admin/filer/actions.html:14 #, python-format msgid "Select all %(total_count)s files and/or folders" -msgstr "" +msgstr "Selecionar todos os %(total_count)s arquivo(s) e/ou pasta(s)" -#: templates/admin/filer/actions.html:13 +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 msgid "Clear selection" -msgstr "" +msgstr "Limpar a seleção" #: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 msgid "Go back to admin homepage" -msgstr "Volte à página inicial de administração" +msgstr "Voltar à página inicial de administração" #: templates/admin/filer/breadcrumbs.html:4 -#: templates/admin/filer/folder/change_form.html:7 -#: templates/image_filer/image_export_form.html:7 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 msgid "Home" msgstr "Início" #: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 msgid "Go back to Filer app" -msgstr "Volte para Filer app" - -#: templates/admin/filer/breadcrumbs.html:5 -#: templates/admin/filer/folder/change_form.html:8 -#: templates/image_filer/image_export_form.html:8 -msgid "Filer" -msgstr "Filer" +msgstr "Voltar para Filer app" #: templates/admin/filer/breadcrumbs.html:6 -#: templates/image_filer/image_export_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:35 msgid "Go back to root folder" msgstr "Volte à pasta raiz" #: templates/admin/filer/breadcrumbs.html:8 -#: templates/admin/filer/breadcrumbs.html:11 -#: templates/admin/filer/folder/change_form.html:11 -#: templates/image_filer/image_export_form.html:12 -#: templates/image_filer/image_export_form.html:14 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 #, python-format msgid "Go back to '%(folder_name)s' folder" msgstr "Volte para a pasta '%(folder_name)s'" -#: templates/admin/filer/change_form.html:28 -msgid "duplicates" -msgstr "duplicatas" - -#: templates/admin/filer/delete_confirmation.html:13 -#, python-format -msgid "" -"Deleting the %(object_name)s '%(escaped_object)s' would result in deleting " -"related objects, but your account doesn't have permission to delete the " -"following types of objects:" -msgstr "" - -#: templates/admin/filer/delete_confirmation.html:21 -#, python-format -msgid "" -"Deleting the %(object_name)s '%(escaped_object)s' would require deleting the " -"following protected related objects:" -msgstr "" - -#: templates/admin/filer/delete_confirmation.html:29 -#, python-format -msgid "" -"Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? " -"All of the following related items will be deleted:" -msgstr "" - -#: templates/admin/filer/delete_confirmation.html:34 -#: templates/admin/filer/delete_selected_files_confirmation.html:45 -msgid "Yes, I'm sure" -msgstr "" +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "Duplicados" #: templates/admin/filer/delete_selected_files_confirmation.html:11 msgid "" @@ -486,399 +642,633 @@ msgid "" "objects, but your account doesn't have permission to delete the following " "types of objects:" msgstr "" +"Remover os arquivo(s) e/ou pasta(s) selecionados resultará na remoção de " +"objetos relacionados, mas sua conta não tem permissão para remover os " +"seguintes tipos de objetos:" #: templates/admin/filer/delete_selected_files_confirmation.html:19 msgid "" "Deleting the selected files and/or folders would require deleting the " "following protected related objects:" msgstr "" +"Remover os arquivo(s) e/ou pasta(s) selecionados, requer remover os seguites " +"objetos protegidos relacionados:" #: templates/admin/filer/delete_selected_files_confirmation.html:27 msgid "" "Are you sure you want to delete the selected files and/or folders? All of " "the following objects and their related items will be deleted:" msgstr "" +"Você tem certeza que deseja remover os arquivo(s) e/ou pasta(s) " +"selecionados? Todos os seguintes objetos e itens relacionados serão " +"removidos: " -#: templates/admin/filer/folder/change_form.html:7 -#: templates/admin/filer/folder/change_form.html:8 -#: templates/admin/filer/folder/change_form.html:9 -#: templates/admin/filer/folder/directory_listing.html:74 -#: templates/image_filer/image_export_form.html:7 -#: templates/image_filer/image_export_form.html:8 -#: templates/image_filer/image_export_form.html:16 -msgid "Go back to" -msgstr "Volte para" +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "Não, me leve de volta" -#: templates/admin/filer/folder/change_form.html:7 -#: templates/image_filer/image_export_form.html:7 -msgid "admin homepage" -msgstr "homepage admin" +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "Sim, eu tenho certeza" -#: templates/admin/filer/folder/change_form.html:22 -#: templates/admin/filer/image/change_form.html:9 +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 msgid "History" msgstr "História" +#: templates/admin/filer/file/change_form.html:37 #: templates/admin/filer/folder/change_form.html:23 -#: templates/admin/filer/image/change_form.html:10 +#: templates/admin/filer/image/change_form.html:37 msgid "View on site" -msgstr "Veja no site" +msgstr "Ver no site" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "Voltar para" -#: templates/admin/filer/folder/change_form.html:35 -#: templates/admin/filer/folder/directory_listing.html:75 -#: templates/admin/filer/folder/directory_listing.html:85 -#: templates/admin/filer/folder/directory_table.html:23 +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "página inicial de administração" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 msgid "Folder Icon" msgstr "Ícone da Pasta" -#: templates/admin/filer/folder/choose_copy_destination.html:12 +#: templates/admin/filer/folder/choose_copy_destination.html:23 msgid "" "Your account doesn't have permissions to copy all of the selected files and/" "or folders." msgstr "" +"Sua conta não possui permissão para copiar todos os arquivo(s) e/ou pasta(s) " +"selecionados." -#: templates/admin/filer/folder/choose_copy_destination.html:15 -#: templates/admin/filer/folder/choose_move_destination.html:15 +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "Me leve de volta" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 msgid "There are no destination folders available." -msgstr "" +msgstr "Não existe pasta de destino disponível." -#: templates/admin/filer/folder/choose_copy_destination.html:18 +#: templates/admin/filer/folder/choose_copy_destination.html:35 msgid "There are no files and/or folders available to copy." -msgstr "" +msgstr "Não existem arquivo(s) e/ou pasta(s) disponíveis para copiar." -#: templates/admin/filer/folder/choose_copy_destination.html:20 +#: templates/admin/filer/folder/choose_copy_destination.html:40 msgid "" "The following files and/or folders will be copied to a destination folder " "(retaining their tree structure):" msgstr "" +"Os arquivo(s) e/ou pasta(s) serão copiados para a pasta de destino (mantendo " +"a estrutura de diretórios):" -#: templates/admin/filer/folder/choose_copy_destination.html:32 -#: templates/admin/filer/folder/choose_move_destination.html:32 +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 msgid "Destination folder:" -msgstr "" +msgstr "Pasta de destino:" -#: templates/admin/filer/folder/choose_copy_destination.html:39 +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 msgid "Copy" -msgstr "" +msgstr "Copiar" -#: templates/admin/filer/folder/choose_images_resize_options.html:12 +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "Não é permitido copiar arquivos para a mesma pasta" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 msgid "" "Your account doesn't have permissions to resize all of the selected images." msgstr "" +"Sua conta não possui permissão para redimensionar todas as imagens " +"selecionadas." -#: templates/admin/filer/folder/choose_images_resize_options.html:15 +#: templates/admin/filer/folder/choose_images_resize_options.html:18 msgid "There are no images available to resize." -msgstr "" +msgstr "Não existem imagens disponíveis para redimensionar." -#: templates/admin/filer/folder/choose_images_resize_options.html:17 +#: templates/admin/filer/folder/choose_images_resize_options.html:20 msgid "The following images will be resized:" -msgstr "" - -#: templates/admin/filer/folder/choose_images_resize_options.html:30 -msgid "Choose an existing thumbnail option or enter resize parameters:" -msgstr "" +msgstr "As seguintes imagens serão redimensionadas:" #: templates/admin/filer/folder/choose_images_resize_options.html:32 -msgid "Choose resize parameters:" +msgid "Choose an existing thumbnail option or enter resize parameters:" msgstr "" +"Selecionar uma opção de miniatura ou digitar os parâmetros de " +"redimensionamento:" -#: templates/admin/filer/folder/choose_images_resize_options.html:35 +#: templates/admin/filer/folder/choose_images_resize_options.html:36 msgid "" "Warning: Images will be resized in-place and originals will be lost. Maybe " "first make a copy of them to retain the originals." msgstr "" +"Cuidado: as imagens serão redimensionadas no mesmo local e os originais " +"serão perdidos. Uma sugestão seria fazer uma cópia para guardar os originais." -#: templates/admin/filer/folder/choose_images_resize_options.html:36 +#: templates/admin/filer/folder/choose_images_resize_options.html:39 msgid "Resize" -msgstr "" +msgstr "Redimensionar" -#: templates/admin/filer/folder/choose_move_destination.html:12 +#: templates/admin/filer/folder/choose_move_destination.html:35 msgid "" "Your account doesn't have permissions to move all of the selected files and/" "or folders." msgstr "" +"Sua conta não possui permissão para mover todos os arquivo(s) e/ou pasta(s) " +"selecionados." -#: templates/admin/filer/folder/choose_move_destination.html:18 +#: templates/admin/filer/folder/choose_move_destination.html:47 msgid "There are no files and/or folders available to move." -msgstr "" +msgstr "Não existem arquivo(s) e/ou pasta(s) disponíveis para mover." -#: templates/admin/filer/folder/choose_move_destination.html:20 +#: templates/admin/filer/folder/choose_move_destination.html:52 msgid "" "The following files and/or folders will be moved to a destination folder " "(retaining their tree structure):" msgstr "" +"Os arquivo(s) e/ou pasta(s) serão movidos para a pasta de destino (mantendo " +"a estrutura de diretórios):" -#: templates/admin/filer/folder/choose_move_destination.html:38 +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 msgid "Move" -msgstr "" +msgstr "Mover" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "Não é permitido mover arquivos na mesma pasta" -#: templates/admin/filer/folder/choose_rename_format.html:12 +#: templates/admin/filer/folder/choose_rename_format.html:15 msgid "" "Your account doesn't have permissions to rename all of the selected files." msgstr "" +"Sua conta não possui permissão para renomear todos os arquivos selecionados." -#: templates/admin/filer/folder/choose_rename_format.html:15 +#: templates/admin/filer/folder/choose_rename_format.html:18 msgid "There are no files available to rename." -msgstr "" +msgstr "Não existem arquivos disponíveis para renomear." -#: templates/admin/filer/folder/choose_rename_format.html:17 +#: templates/admin/filer/folder/choose_rename_format.html:20 msgid "" "The following files will be renamed (they will stay in their folders and " "keep original filename, only displayed filename will be changed):" msgstr "" +"Os seguintes arquivos serão renomeados (estes arquivos serão mantidos em " +"suas pastas e os nomes originais serão mantidos, apenas o nome de " +"apresentação será alterado):" -#: templates/admin/filer/folder/choose_rename_format.html:54 +#: templates/admin/filer/folder/choose_rename_format.html:59 msgid "Rename" -msgstr "" +msgstr "Renomear" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "Volte para a pasta pai" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "Alterar os detalhes da pasta atual" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "Alterar" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "Clique aqui para pesquisar pela frase inserida" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "Pesquisar" -#: templates/admin/filer/folder/directory_listing.html:66 +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "Fechar" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "Limite" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "Marque para limitar a pesquisa na pasta atual" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "Limitar a pesquisa na pasta atual" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "Remover" + +#: templates/admin/filer/folder/directory_listing.html:203 msgid "Adds a new Folder" msgstr "Adiciona uma nova pasta" -#: templates/admin/filer/folder/directory_listing.html:66 -#: templates/image_filer/include/export_dialog.html:34 +#: templates/admin/filer/folder/directory_listing.html:206 msgid "New Folder" msgstr "Nova Pasta" -#: templates/admin/filer/folder/directory_listing.html:67 -msgid "upload files" -msgstr "" +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "Enviar arquivos" -#: templates/admin/filer/folder/directory_listing.html:67 -msgid "Upload" -msgstr "" +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "Você precisa selecionar a pasta primeiro" -#: templates/admin/filer/folder/directory_listing.html:74 -msgid "Go back to the parent folder" -msgstr "Volte para a pasta pai" +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "Nome" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "Proprietário" -#: templates/admin/filer/folder/directory_listing.html:76 -#: templates/admin/filer/folder/directory_table.html:29 -#: templates/admin/filer/tools/search_form.html:18 +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "Tamanho" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "Ação" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 #, python-format -msgid "1 folder" +msgid "Change '%(item_label)s' folder details" +msgstr "Alterar os detalhes da pasta '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" msgid_plural "%(counter)s folders" msgstr[0] "%(counter)s pasta" msgstr[1] "%(counter)s pastas" +msgstr[2] "%(counter)s pastas" -#: templates/admin/filer/folder/directory_listing.html:76 -#: templates/admin/filer/folder/directory_table.html:29 -#: templates/admin/filer/tools/search_form.html:19 +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 #, python-format -msgid "1 file" +msgid "%(counter)s file" msgid_plural "%(counter)s files" msgstr[0] "%(counter)s arquivo" msgstr[1] "%(counter)s arquivos" - -#: templates/admin/filer/folder/directory_listing.html:80 -msgid "Change current folder details" -msgstr "Alterar os detalhes da pasta atual" - -#: templates/admin/filer/folder/directory_listing.html:80 -#: templates/admin/filer/folder/directory_table.html:27 -#: templates/admin/filer/folder/directory_table.html:43 -msgid "Change" -msgstr "Alterar" - -#: templates/admin/filer/folder/directory_table.html:13 -msgid "Name" -msgstr "Nome" - -#: templates/admin/filer/folder/directory_table.html:23 -#: templates/admin/filer/folder/directory_table.html:27 -#: templates/admin/filer/folder/directory_table.html:29 -#, python-format -msgid "Change '%(item_label)s' folder details" -msgstr "Alterar os detalhes da pasta '%(item_label)s'" - -#: templates/admin/filer/folder/directory_table.html:30 -#: templates/admin/filer/folder/directory_table.html:45 -msgid "Owner" -msgstr "Proprietário" - -#: templates/admin/filer/folder/directory_table.html:37 +msgstr[2] "%(counter)s arquivos" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "Alterar detalhes da pasta" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "Remover pasta" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 msgid "Select this file" -msgstr "Selecione este arquivo" +msgstr "Selecionar este arquivo" -#: templates/admin/filer/folder/directory_table.html:39 -#: templates/admin/filer/folder/directory_table.html:43 -#: templates/admin/filer/folder/directory_table.html:44 +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 #, python-format msgid "Change '%(item_label)s' details" msgstr "Alterar os detalhes de '%(item_label)s'" -#: templates/admin/filer/folder/directory_table.html:42 -#, python-format -msgid "Delete '%(item_label)s'" -msgstr "" - -#: templates/admin/filer/folder/directory_table.html:42 -msgid "Delete" -msgstr "" - -#: templates/admin/filer/folder/directory_table.html:46 +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 msgid "Permissions" msgstr "Permissões" -#: templates/admin/filer/folder/directory_table.html:46 +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 msgid "disabled" msgstr "desabilitado" -#: templates/admin/filer/folder/directory_table.html:46 +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 msgid "enabled" msgstr "habilitado" -#: templates/admin/filer/folder/directory_table.html:50 -msgid "Move to clipboard" -msgstr "Mover para a área de transferência" +#: templates/admin/filer/folder/directory_table_list.html:144 +#, fuzzy +#| msgid "Move selected files to clipboard" +msgid "URL copied to clipboard" +msgstr "Mover os arquivos selecionados para a área de transferência" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "URL Canônico '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "Baixar '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "Remover arquivo" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "Arraste os arquivos aqui ou use o botão \"Enviar arquivos\"" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "Arraste seu arquivo para enviar em:" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "Upload" -#: templates/admin/filer/folder/directory_table.html:58 -msgid "there are no files or subfolders" -msgstr "não existem arquivos ou subpastas" +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "Cancelar" -#: templates/admin/filer/folder/directory_table.html:65 +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "Envio realizado com sucesso!" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "Envio cancelado!" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 msgid "previous" -msgstr "" +msgstr "anterior" -#: templates/admin/filer/folder/directory_table.html:69 +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 #, python-format -msgid "" -"\n" -" Page %(number)s of %(num_pages)s.\n" -" " -msgstr "" +msgid "Page %(number)s of %(num_pages)s." +msgstr "Página %(number)s de %(num_pages)s." -#: templates/admin/filer/folder/directory_table.html:75 +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 msgid "next" +msgstr "próximo" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "Selecione todos %(total_count)s" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" msgstr "" #: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 msgid "Add new" msgstr "Adicionar novo" -#: templates/admin/filer/folder/new_folder_form.html:13 +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "Administração Django" + +#: templates/admin/filer/folder/new_folder_form.html:15 msgid "Please correct the error below." msgid_plural "Please correct the errors below." -msgstr[0] "" -msgstr[1] "" +msgstr[0] "Favor corrigir o erro abaixo." +msgstr[1] "Favor corrigir os erros abaixo." +msgstr[2] "Favor corrigir os erros abaixo." -#: templates/admin/filer/folder/new_folder_form.html:28 +#: templates/admin/filer/folder/new_folder_form.html:30 msgid "Save" msgstr "Salvar" -#: templates/admin/filer/image/change_form.html:21 -msgid "Full size preview" -msgstr "visualização de tamanho completo" +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" -#: templates/admin/filer/tools/search_form.html:8 -#: templates/admin/filer/tools/search_form.html:14 -msgid "Search" -msgstr "Pesquisa" +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" -#: templates/admin/filer/tools/search_form.html:13 -msgid "Enter your search phrase here" -msgstr "Digite sua frase de busca aqui" +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "Área de transferência" -#: templates/admin/filer/tools/search_form.html:14 -msgid "Click here to" -msgstr "Clique aqui para" +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "Colar todos os itens aqui" -#: templates/admin/filer/tools/search_form.html:14 -msgid "run search for entered phrase" -msgstr "executar pesquisa para a frase inscrita" +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "Mova todos os arquivos da área de transferência para" -#: templates/admin/filer/tools/search_form.html:15 -msgid "Check it to" -msgstr "Verifique se a" +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "Esvaziar área de transferência" -#: templates/admin/filer/tools/search_form.html:15 -#: templates/admin/filer/tools/search_form.html:16 -msgid "limit the search to current folder" -msgstr "limitar a pesquisa a pasta atual" +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "a área de transferência está vazia" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "Falha no upload" -#: templates/admin/filer/tools/search_form.html:18 +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "Tipo" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "Tamanho do arquivo" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "Modificado" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "Criado" + +#: templates/admin/filer/tools/search_form.html:5 msgid "found" msgstr "encontrados" -#: templates/admin/filer/tools/search_form.html:18 +#: templates/admin/filer/tools/search_form.html:5 msgid "and" msgstr "e" -#: templates/admin/filer/tools/search_form.html:19 +#: templates/admin/filer/tools/search_form.html:7 msgid "cancel search" msgstr "cancelar a busca de" -#: templates/admin/filer/tools/upload_button_js.html:24 -#: templates/admin/filer/widgets/admin_file.html:7 -#: templates/admin/filer/widgets/admin_file.html:8 -msgid "file missing" -msgstr "arquivo faltando" +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "Limpar" -#: templates/admin/filer/tools/clipboard/clipboard.html:7 -msgid "Clipboard" -msgstr "Área de transferência" +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "ou arraste seu arquivo aqui" -#: templates/admin/filer/tools/clipboard/clipboard.html:19 -msgid "Paste all items here" -msgstr "Colar todos os itens aqui" +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "nenhum arquivo selecionado" -#: templates/admin/filer/tools/clipboard/clipboard.html:26 -msgid "discard" -msgstr "descartar" +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "Pesquisar" -#: templates/admin/filer/tools/clipboard/clipboard.html:26 -msgid "Move all clipboard files to" -msgstr "Mova todos os arquivos da área de transferência para" +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "Alterar Arquivo" -#: templates/admin/filer/tools/clipboard/clipboard.html:43 -msgid "the clipboard is empty" -msgstr "a área de transferência está vazia" +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" -#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:11 -msgid "upload failed" -msgstr "Falha no upload" +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" -#: templates/admin/filer/widgets/admin_file.html:11 -msgid "no file selected" -msgstr "nenhum arquivo selecionado" +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" -#: templates/admin/filer/widgets/admin_file.html:14 -#: templates/admin/filer/widgets/admin_file.html:15 -#: templates/admin/filer/widgets/admin_folder.html:7 -#: templates/admin/filer/widgets/admin_folder.html:8 -msgid "Lookup" -msgstr "Pesquisa" +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" -#: templates/admin/filer/widgets/admin_file.html:17 -#: templates/admin/filer/widgets/admin_folder.html:10 -msgid "Clear" -msgstr "Limpar" +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" -#: templates/admin/filer/widgets/admin_folder.html:5 -msgid "none selected" +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" msgstr "" -#: templates/image_filer/folder.html:3 -#, python-format -msgid "Folder '%(folder_label)s' files" -msgstr "Arquivos da pasta '%(folder_label)s'" +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" -#: templates/image_filer/folder.html:6 -msgid "File name" -msgstr "Nome do arquivo" +#~ msgid "none selected" +#~ msgstr "none selected" -#: templates/image_filer/image_export_form.html:17 -msgid "export" -msgstr "exportação" +#~ msgid "Add Folder" +#~ msgstr "Add Folder" -#: templates/image_filer/image_export_form.html:27 -msgid "download image" -msgstr "download da imagem" +#~ msgid "Subject Location" +#~ msgstr "Subject location" -#: templates/image_filer/include/export_dialog.html:13 -msgid "Folder name already taken." -msgstr "Nome da pasta já existe." +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" +#~ msgstr[2] "15c0f2d28d6dab1af1f6d94906beb627_pl_2" -#: templates/image_filer/include/export_dialog.html:15 -msgid "Submit" -msgstr "Enviar" +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/ru/LC_MESSAGES/django.mo b/filer/locale/ru/LC_MESSAGES/django.mo new file mode 100644 index 000000000..05996b220 Binary files /dev/null and b/filer/locale/ru/LC_MESSAGES/django.mo differ diff --git a/filer/locale/ru/LC_MESSAGES/django.po b/filer/locale/ru/LC_MESSAGES/django.po new file mode 100644 index 000000000..89f63fdbb --- /dev/null +++ b/filer/locale/ru/LC_MESSAGES/django.po @@ -0,0 +1,1263 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +# Alexander Naydenko , 2020 +# Oleg Fish , 2017 +# Pavel , 2012 +# Pavel , 2012 +# Vladimir Puzakov , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Alexander Naydenko , 2020\n" +"Language-Team: Russian (http://app.transifex.com/divio/django-filer/language/" +"ru/)\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || " +"(n%100>=11 && n%100<=14)? 2 : 3);\n" + +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "" + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "Дополнительно" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "канонический URL" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" +"Для выполнения действий нужно выбрать хотя бы один объект. Не произведено " +"никаких изменений." + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "%(total_count)s выбран" +msgstr[1] "%(total_count)s выбрано" +msgstr[2] "Все %(total_count)s выбраны" +msgstr[3] "Все %(total_count)s выбраны" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "Содержимое %(folder_name)s" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "0 из %(cnt)s выбрано" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "Действие не выбрано." + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "Успешно перемещено %(count)d файлов в буфер обмена." + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "Переместить выбранные файлы в буфер обмена" + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "Разрешения успешно отключены для %(count)d файлов." + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "Разрешения успешно применены для %(count)d файлов." + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "Включить разрешения для выбранных файлов" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "Отключить разрешения для выбранных файлов" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "Успешно удалено %(count)d файлов/папок." + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "Невозможно удалить файлы/папки" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "Вы уверены?" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "Удалить файлы/папки" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "Удалить выбранные файлы/папки" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "Папки с именами %s уже существуют в указанном месте" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "Успешно перемещено %(count)d файлов/папок в папку '%(destination)s'." + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "Переместить файлы/папки" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "Переместить выбранные файлы/папки" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "Успешно переименовано %(count)d файлов." + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "Переименовать файлы" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "Успешно скопировано %(count)d файлов/папок в папку '%(destination)s'." + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "Скопировать файлы/папки" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "Скопировать выбранные файлы/папки" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "Успешно изменен размер %(count)d изображений." + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "Изменить размер изображений" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "Изменить размер выбранных изображений" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "Окончание, которое будет добавлено к именам скопированных файлов." + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "" +"Окончание должно быть правильной, простой и в нижнем регистре частью имени " +"файла, например \"%(valid)s\"." + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "Неизвестный ключ форматирования \"%(key)s\"." + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "Неверный формат переименования: %(error)s." + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "опция миниатюры" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "ширина" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "высота" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "обрезать" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "увеличивать" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "Опция миниатюры или параметры изменения размера должны быть указаны." + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "Расположение объекта" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "Расположение главного объекта сцены. Формат: \"x,y\"." + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "Неверный формат расположения объекта." + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "Расположение объекта указано за пределами изображения." + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "Вы ввели: \"{subject_location}\". " + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "Папка с таким именем уже существует" + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "Filer" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "Медиа-библиотека" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "альтернативный текст" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "описание" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "расположение объекта" + +#: models/abstract.py:91 +msgid "image" +msgstr "изображение" + +#: models/abstract.py:92 +msgid "images" +msgstr "изображения" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "пользователь" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "файлы" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "буфер обмена" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "буферы обмена" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "файл" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "элемент буфера обмена" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "элементы буфера обмена" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "папка" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "размер файла" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "sha1" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "это обязательные данные" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "оригинальное имя файла" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "имя" + +#: models/filemodels.py:116 +msgid "description" +msgstr "описание" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "владелец" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "загружено" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "изменено" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "Разрешения отключены" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" +"Отменить все проверки разрешений для этого файла. Файл будет доступен " +"публично для каждого." + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "создан" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "Папка" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "Папки" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "все элементы" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "только этот элемент" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "этот элемент и потомки" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "разрешить" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "запретить" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "тип" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "группа" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "все" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "могут читать" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "могут редактировать" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "могут добавлять потомков" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "разрешение папки" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "разрешения папки" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "" + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "дата создания" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "автор" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "необходимо всегда указывать авторство" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "необходимо всегда указывать copyright" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "ширина в пикселях." + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "высота в пикселях." + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "опции миниатюры" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "Несортированные загрузки" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "файлы с отсутсвующими метаданными" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "корень" + +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "Выполнить выбранное действие" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "Выполнить" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "Нажмите здесь, чтобы выбрать объекты на всех страницах" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "Выбрать все %(total_count)s файлов/папок" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "Очистить выбор" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "Вернуться на главную страницу администрирования" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "Домой" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "Вернуться на главную Filer'а" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "Вернуться в корневую папку" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "Вернуться в папку \"%(folder_name)s\"" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "Дубликаты" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" +"Удаление выбранных файлов/папок приведет к удалению связанных объектов, но у " +"вас нет прав удалять следующие объекты:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "" +"Удаление выбранных файлов/папок потребует удаления следующих защищенных " +"связанных объектов:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "" +"Вы уверены, что хотите удалить выбранные файлы/папки? Следующие объекты " +"вместе со связанными объектами будут удалены:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "Нет, пустите меня обратно" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "Да, я уверен" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "История" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "Посмотреть на сайте" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "Вернуться к" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "главная страница администрирования" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "Иконка папки" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." +msgstr "У вас нет прав на копирование выбранных файлов/папок" + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "Пустите меня обратно" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "Нет доступной целевой папки." + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "Нет файлов для копирования." + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "" +"Эти файлы/папки будут скопированы в целевую папку (с сохранением " +"иерархичности):" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "Целевая папка:" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "Копировать" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "Копирование файлов в ту же самую папку запрещено" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "Вы не имеете прав для изменения размеров выбранных изображений." + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "Нет доступных изображений для изменения размеров." + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "У этих изображений будет изменен размер:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "Выберите опцию миниатюры или введите параметры изменения размеров:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "" +"Внимание: изображения будут изменены в размерах с заменой оригиналов. " +"Возможно, лучше будет сперва сделать копии." + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "Изменить размеры" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." +msgstr "Вы не имеете прав для перемещения выбранных файлов/папок." + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "Нет файлов/папок для перемещения." + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "" +"Следующие файлы/папки будут перемещены в целевую папку (сохраняя " +"иерархичность):" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "Переместить" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "Перемещение файлов в ту же самую папку запрещено" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "У вас нет прав на переименование выбранных файлов." + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "Нет файлов для переименовывания." + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "" +"Эти файлы будут переименованы (они остануться в их папках и сохранят имена " +"оригинальных файлов, только отображаемое имя измениться):" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "Переименовать" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "Возвратиться к родительской папке" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "Изменить текущую папку" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "Изменить" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "Нажмите здесь для поиска по введенной фразе" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "Поиск" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "Закрыть" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "Ограничить" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "Отметьте, чтобы ограничить поиск текущей папкой" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "Ограничить поиск текущей папкой" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "Удалить" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "Добавляет новую папку" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "Новая папка" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "Загрузить файлы" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "Сначала надо выбрать папку" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "Имя" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "Владелец" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "Размер" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "Действие" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "Изменить данные папки \"%(item_label)s\"" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "%(counter)s папка" +msgstr[1] "%(counter)s папки" +msgstr[2] "%(counter)s папок" +msgstr[3] "%(counter)s папок" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "%(counter)s файл" +msgstr[1] "%(counter)s файла" +msgstr[2] "%(counter)s файлов" +msgstr[3] "%(counter)s файлов" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "Изменить свойства папки" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "Удалить папку" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "Выбрать этот файл" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "Изменить данные \"%(item_label)s\"" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "Разрешения" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "отключены" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "включены" + +#: templates/admin/filer/folder/directory_table_list.html:144 +#, fuzzy +#| msgid "Move selected files to clipboard" +msgid "URL copied to clipboard" +msgstr "Переместить выбранные файлы в буфер обмена" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "Канонический URL '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "Скачать '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "Удалить файл" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "\"Скиньте\" сюда файлы или используйте кнопку \"Загрузить файлы\"" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "\"Скиньте\" ваши файлы сюда для загрузки в:" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "Загрузить" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "отмена" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "Загрузка успешно завершена!" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "Загрузка отменена!" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "предыдущая" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "Страница %(number)s из %(num_pages)s." + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "следующая" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "Выбрать все %(total_count)s" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "Добавить новую" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "Система администрирования Django" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "Пожалуйста, исправьте указанную ошибку." +msgstr[1] "Пожалуйста, исправьте указанные ошибки." +msgstr[2] "Пожалуйста, исправьте указанные ошибки." +msgstr[3] "Пожалуйста, исправьте указанные ошибки." + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "Сохранить" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "Буфер обмена" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "Вставить все элементы здесь" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "Переместить элементы буфера обмена в" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "Пустой буфер обмена" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "буфер обмена пуст" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "загрузка не удалась" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "Тип" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "Размер файла" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "Изменен" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "Создан" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "найдено" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "и" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "закрыть поиск" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "Очистить" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "или \"скиньте\" ваш файл сюда" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "файл не выбран" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "Выбрать" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "Выбрать файл" + +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" +#~ msgstr[2] "15c0f2d28d6dab1af1f6d94906beb627_pl_2" +#~ msgstr[3] "15c0f2d28d6dab1af1f6d94906beb627_pl_3" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/sk/LC_MESSAGES/django.mo b/filer/locale/sk/LC_MESSAGES/django.mo new file mode 100644 index 000000000..439890714 Binary files /dev/null and b/filer/locale/sk/LC_MESSAGES/django.mo differ diff --git a/filer/locale/sk/LC_MESSAGES/django.po b/filer/locale/sk/LC_MESSAGES/django.po new file mode 100644 index 000000000..5edca14bd --- /dev/null +++ b/filer/locale/sk/LC_MESSAGES/django.po @@ -0,0 +1,1235 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Angelo Dini \n" +"Language-Team: Slovak (http://app.transifex.com/divio/django-filer/language/" +"sk/)\n" +"Language: sk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n " +">= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);\n" + +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "" + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "" + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "" + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "" + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "" + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "" + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "" + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "" + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "" + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "" + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "" + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "" + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "" + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "" + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "" + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "" + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "" + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "" + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "" + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "" + +#: models/abstract.py:91 +msgid "image" +msgstr "" + +#: models/abstract.py:92 +msgid "images" +msgstr "" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "" + +#: models/filemodels.py:116 +msgid "description" +msgstr "" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "" + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "" + +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:144 +msgid "URL copied to clipboard" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "" + +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" +#~ msgstr[2] "15c0f2d28d6dab1af1f6d94906beb627_pl_2" +#~ msgstr[3] "15c0f2d28d6dab1af1f6d94906beb627_pl_3" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/tr/LC_MESSAGES/django.mo b/filer/locale/tr/LC_MESSAGES/django.mo new file mode 100644 index 000000000..d1049348f Binary files /dev/null and b/filer/locale/tr/LC_MESSAGES/django.mo differ diff --git a/filer/locale/tr/LC_MESSAGES/django.po b/filer/locale/tr/LC_MESSAGES/django.po new file mode 100644 index 000000000..2437c3922 --- /dev/null +++ b/filer/locale/tr/LC_MESSAGES/django.po @@ -0,0 +1,1230 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +# Cihad GÜNDOĞDU , 2013,2015-2016 +# Cihad GÜNDOĞDU , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Cihad GÜNDOĞDU , 2013,2015-2016\n" +"Language-Team: Turkish (http://app.transifex.com/divio/django-filer/language/" +"tr/)\n" +"Language: tr\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" + +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "" + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "Gelişmiş" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "standart URL" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "" +msgstr[1] "" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "%(cnt)s 0 adet seçildi" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "İşlem seçilmedi" + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "%(count)d adet dosya arabelleğe taşındı" + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "Seçili dosyalar ara belleğe alındı" + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "%(count)d adet dosyanın yetkilendirmesi pasif hale getirildi." + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "%(count)d adet dosyanın yetkilendirmesi pasif hale getirildi." + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "Seçili dosyalar için yetkilendirmeyi aktif yap" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "Seçili dosyalar için yetkilendirmeyi pasif yap" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "%(count)d dosya veya klasörler başarıyla silindi" + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "Seçili dosya veya klasörler silinemedi" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "Eminmisiniz?" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "Dosya veya klasörleri sil" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "Seçili dosya veya klasörleri sil" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "%s isimli klasörler seçili hedefte var." + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" +"%(count)d adet dosya/klasör başarıyla '%(destination)s' klasörüne taşındı" + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "Dosya veya klasörleri taşı" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "Seçili dosya veya klasörleri taşı" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "%(count)d adet dosya yeniden adlandırıldı." + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "Dosyaları yeniden adlandır" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" +"%(count)d adet dosya veya klasör '%(destination)s' klasörüne kopyalandı" + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "Dosya veya klasörleri kopyala" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "Seçili dosya veya klasörleri kopyala" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "%(count)d adet resim başarıyla yeniden boyutlandırıldı." + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "Resimleri yeniden boyutlandır" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "Seçili resimleri yeniden boyutlandır" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "" + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "" + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "" + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "" + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "genişlil" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "yükseklik" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "kırp" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "" + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "" + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "" + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "" + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "" + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "Bu isimde dizin zaten var" + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "" + +#: models/abstract.py:91 +msgid "image" +msgstr "" + +#: models/abstract.py:92 +msgid "images" +msgstr "" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "kullanıcı" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "dosyalar" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "ara bellek" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "ara bellekler" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "dosya" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "arabellek nesnesi" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "klasör" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "dosya boyutu" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "sha1" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "orjinal dosya adı" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "isim" + +#: models/filemodels.py:116 +msgid "description" +msgstr "açıklama" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "sahib" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "yüklendi" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "düzenlendi" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "Yetkiler pasifleştirildi" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "tüm elemanlar" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "sadece bu eleman" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "bu eleman ve alt elemanlar" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "izin ver" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "engelle" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "tip" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "grup" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "herkes" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "okuyabilir" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "düzenleyebilir" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "alt eleman ekleyebilir" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "dizin yetki" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "dizin yetkileri" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "" + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "kök" + +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "Seçili aksiyonu çalışıtır" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "Git" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "Yeniden adlandır" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "Ara" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "Geçerli klasörün aramalarını sınırla" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "Sil" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "Yeni Klasör Ekle" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "Yeni Klasör" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "Dosyaları Yükle" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "Önce bir klasör seçmelisin" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "İsim" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "Sahip" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "Boyut" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "İşlem" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "'%(item_label)s' klasör detaylarını değiştir" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "" +msgstr[1] "" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "" +msgstr[1] "" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "Klasör detaylarını değiştir" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "Klasörü kaldır" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "Bu dosyayı seç" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "'%(item_label)s' detaylarını değiştir" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "Yetkiler" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "pasif" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "aktif" + +#: templates/admin/filer/folder/directory_table_list.html:144 +#, fuzzy +#| msgid "Move selected files to clipboard" +msgid "URL copied to clipboard" +msgstr "Seçili dosyalar ara belleğe alındı" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "Dosyayı kaldır" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "Buraya dosya yüklemek için \"Dosyaları Yükle\" düğmesine tıklayın" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "Yüklenecek dosyayı buraya bırakın" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "Yükle" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "iptal" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "Yükleme Başarılı" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "Yükleme iptal!" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "önceki" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "Sayfa %(number)s / %(num_pages)s." + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "sonraki" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "%(total_count)s Tümünü seç" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "Yeni ekle" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "" +msgstr[1] "" + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "Kaydet" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "Ara bellek" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "Tüm elemanları buraya yapıştır" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "Arabellekteki tüm dosyaları kopyala" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "Bellek boş" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "Arabellek boş" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "Yükleme başarısız" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "Tip" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "Dosya-Boyut" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "Düzenlendi" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "Oluşturuldu" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "bulundu" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "ve" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "arama iptal" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "Temizle" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "Seçili dosya yok" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "Dosya Seç" + +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" +#~ msgstr[1] "15c0f2d28d6dab1af1f6d94906beb627_pl_1" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/vi_VN/LC_MESSAGES/django.mo b/filer/locale/vi_VN/LC_MESSAGES/django.mo new file mode 100644 index 000000000..c784f9621 Binary files /dev/null and b/filer/locale/vi_VN/LC_MESSAGES/django.mo differ diff --git a/filer/locale/vi_VN/LC_MESSAGES/django.po b/filer/locale/vi_VN/LC_MESSAGES/django.po new file mode 100644 index 000000000..24ac1a3a7 --- /dev/null +++ b/filer/locale/vi_VN/LC_MESSAGES/django.po @@ -0,0 +1,1252 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +# Duong Vu Hong , 2021 +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Duong Vu Hong , 2021\n" +"Language-Team: Vietnamese (Viet Nam) (http://app.transifex.com/divio/django-" +"filer/language/vi_VN/)\n" +"Language: vi_VN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "" + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "Nâng Cao" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "URL hợp chuẩn" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" +"Những item được chọn để thực hiện hành động trên đó. Không có item nào bị " +"thay đổi." + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "Tất cả %(total_count)s được chọn" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "Thư mục liệt kê cho %(folder_name)s" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "0 trên %(cnt)sđược chọn" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "Không có hành động được chọn" + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "Di chuyển %(count)dtệp vào bảng tạm thành công" + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "Di chuyển tệp đã chọn vào bảng tạm" + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "Vô hiệu hóa quyền của %(count)dtệp thành công" + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "Kích hoạt quyền của %(count)dtệp thành công" + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "Kích hoạt quyền cho các tệp đã chọn" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "Vô hiệu hóa quyền của các tệp đã chọn" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "Đã xóa %(count)d tệp và/hoặc thư mục thành công. " + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "Không thể xóa các tệp và/hoặc các thư mục" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "Bạn chắc chắn chứ?" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "Xóa các tệp và/hoặc các thư mục" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "Xóa các tệp và/hoặc các thư mục dã chọn" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "Các thư mục với tên %s đã tồn tại ở vị trí đã chọn" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" +"Đã di chuyển %(count)d tệp và/hoặc thư mục tới thư mục '%(destination)s'." + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "Di chuyển tệp và/hoặc thư mục" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "Đã di chuyển tệp và/hoặc thư mục đã chọn" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "Đã thành công đổi tên %(count)d tệp." + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "Đổi tên tệp" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" +"Đã thành công sao chép %(count)d tệp và/hoặc thư mục tới thư mục " +"'%(destination)s'." + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "Sao chép tệp và/hoặc thư mục" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "Sao chép tệp và/hoặc thư mục đã chọn" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "Đã thành công thay đổi kích thước %(count)d ảnh." + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "Thay đổi kích thước ảnh" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "Thay dổi kích thước ảnh đã chọn" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "Hậu tố sẽ được nối vào tên của tệp đã sao chép." + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "" +"Hậu tố phải là một phần tên tệp hợp lệ, đơn giản và chữ thường, như " +"\"%(valid)s\"." + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "Không biết định dạng đổi tên của khóa giá trị \"%(key)s\"." + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "Định dạng đổi tên không hợp lệ: %(error)s." + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "tùy chọn thumbnail" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "Độ rộng" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "Độ cao" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "Xén" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "cao cấp" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "Tùy chọn thumbnail hoặc tham số thay đổi kích thước phải được chọn." + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "Vị trí chủ đề" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "Vị trí của chủ đề chính của của quang cảnh. Định dạng: \"x,y\"." + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "Định dạng vị trí chủ đề không hợp lệ." + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "Vị trí chủ đề ở bên ngoài hình ảnh." + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "Đầu vào của bạn: \"{subject_location}\"." + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "Thư mục với tên này đã tồn tại." + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "Filer" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "Thư viện phương tiện" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "văn bản thay thế mặc định" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "đầu đề mặc định" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "vị trí chủ đề" + +#: models/abstract.py:91 +msgid "image" +msgstr "hình ảnh" + +#: models/abstract.py:92 +msgid "images" +msgstr "những hình ảnh" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "người dùng" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "những tệp" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "bảng tạm" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "những bảng tạm" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "tệp" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "item bảng tạm" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "items bảng tạm" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "thư mục" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "kích thước tệp" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "sha1" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "có tất cả dữ liệu ủy thác" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "tên tệp gốc" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "tên" + +#: models/filemodels.py:116 +msgid "description" +msgstr "mô tả" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "người sở hữu" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "đã tải lên tại" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "đã chỉnh sửa tại" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "Quyền bị vô hiệu hóa" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" +"Vô hiệu hóa bất kỳ quyền kiểm tra cho tệp này. Tệp sẽ truy cập được bởi bất " +"kỳ ai." + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "đã tạo tại" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "Thư mục" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "Những thư mục" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "tất cả đồ" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "chỉ đồ này" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "đồ này và tất cả các con" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "cho phép" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "không cho phép" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "kiểu" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "nhóm" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "tất cả mọi người" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "có thể đọc" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "có thể tùy chỉnh" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "có thể thêm con" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "quyền thư mục" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "những quyền thư mục" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "" + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "ngày nắm giữ" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "tác giả" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "phải luôn công khai tài khoản tác giả" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "phải luôn công khai bản quyền" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "độ rộng bằng pixel" + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "độ cao bằng pixel" + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "những tùy chọn thumbnail" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "Những tải lên chưa sắp xếp" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "những tệp với metadata bị mất" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "gốc" + +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "Chạy hành dộng đã chọn" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "Đi" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "Bấn ở đây để chọn những đối tượng xuyên suốt tất cả các trang" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "Chọn tất cả %(total_count)s tệp và/hoặc thư mục" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "Xóa chọn" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "Trở lại trang chủ người quản trị" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "Trang chủ" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "Trở lại ứng dụng Filer" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "Trở lại thư mục gốc" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "Trở lại '%(folder_name)s' thư mục" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "Lặp" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" +"Xóa tệp và/hoặc thưc mục đã chọn sẽ dẫn đến xóa đối tượng liên quan, nhưng " +"tài khoản của bạn không có quyền xóa những loại của các đối tượng:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "" +"Xóa tệp và/hoặc thư mục đã chọn sẽ yêu cầu xóa những đối tượng liên quan " +"được bảo vệ sau:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "" +"Bạn có chắc muốn xóa tệp và/hoặc thư mục đã chọn? Tất cả những đối tượng và " +"những thứ liên quan đến chúng sẽ bị xóa:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "Không, đưa tôi quay lại" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "Có, Tôi chắc chắn" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "Lịch sử" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "Xem trong trang" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "Quay lại" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "trang chủ người quản trị" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "Biểu tượng thư mục" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." +msgstr "" +"Tài khoản của bạn không có quyền để sao chép tất cả tệp và thư mục được chọn." + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "Đưa tôi quay lại" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "Không có thư mục đích" + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "Không có tệp và/hoặc thư mục để sao chép." + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "" +"Những tệp và thư mục sau sẽ được sao chép tới một thư mục đích (giữ cấu trúc " +"cây thư mục):" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "Thư mục đích:" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "Sao chép" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "Không cho phép sao chép tệp tới cùng thư mục" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "" +"Tài khoản của bạn không có quyền để thay đổi kích thước của tất cả hình ảnh " +"đã chọn." + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "Không có hình ảnh để thay dổi kích thước" + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "Hình ảnh dưới đay sẽ bị thay đổi kích thước:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "" +"Chọn một tùy chọn của thumbnail đang tồn tại hoặc nhập tham số thay đổi kích " +"thước:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "" +"Cảnh bảo: Hình ảnh sẽ bị thay đổi tại chỗ và ảnh gốc sẽ bị mất. Có thể tạo " +"một sao chép của chúng để giữ lại hình ảnh gốc." + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "Thay đổi kích thước" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." +msgstr "" +"Tài khoản của bạn không có quyền để di chuyển tất cả các tệp và thư mục đã " +"chọn." + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "Không có tệp và/hoặc thư mục để di chuyển." + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "" +"Tệp và thư mục dưới đây sẽ được chuyển tới thư mục đích (giữ nguyên cấu trúc " +"cây thư mục):" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "Di chuyển" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "Không cho phép di chuyển tệp vào cùng thư mục" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "Tài khoản của bạn không có quyền để đổi tên tất cả các tệp đã chọn." + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "Không có tệp để đổi tên." + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "" +"Tệp dưới đây sẽ bị đổi tên (chúng vẫn ở trong thư mục của chúng và giữ tên " +"gốc, chỉ tên hiển thị sẽ bị thay đổi):" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "Đổi tên" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "Trở lại thư mục cha" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "Thay đổi thông tin chi tiết thư mục hiện tại" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "Thay đổi" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "Bấm vào đây để chạy tìm kiếm cho đoạn văn đã nhập" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "Tìm kiếm" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "Đóng" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "Giới hạn" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "Chọn để giới hạn tìm kiếm cho thư mục hiện tại" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "Giới hạn tìm kiếm cho thư mục hiện tại" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "Xóa" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "Thêm một thư mục mới" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "Thư mục mới" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "Tải tệp lên" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "Bạn đầu tiên phải chọn một thư mục" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "Tên" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "Người sở hữu" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "Kích thước" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "Hành động" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "Thay đổi thông tin chi tiết thư mục '%(item_label)s' " + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "%(counter)s thư mục" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "%(counter)s tệp" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "Thay dổi thông tin chi tiết thư mục" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "Xóa thư mục" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "Chọn tệp này" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "Thay đổi thông tin chi tiết '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "Quyền" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "đã vô hiệu hóa" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "đã kích hoạt" + +#: templates/admin/filer/folder/directory_table_list.html:144 +#, fuzzy +#| msgid "Move selected files to clipboard" +msgid "URL copied to clipboard" +msgstr "Di chuyển tệp đã chọn vào bảng tạm" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "Url hợp chuẩn '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "Tải '%(item_label)s'" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "Xóa tệp" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "Thả tệp ở đây hoặc sử dụng nút \"Tải tệp lên\"" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "Thả tệp của bạn để tải lên:" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "Tải lên" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "hủy bỏ" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "Tải lên thành công!" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "Tải lên đã bị hủy!" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "trước đó" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "Trang %(number)s trên %(num_pages)s." + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "tiếp theo" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "Chọn tất cả %(total_count)s" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "Thêm mới" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "Trang quản trị Django" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "Hãy sửa lỗi dưới đây." + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "Lưu" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "Bảng tạm" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "Dán những thứ ở đây" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "Di chuyển tất cả tệp bảng tạm tới" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "Làm rỗng bảng tạm" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "bảng tạm rỗng" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "tải lên lỗi" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "Kiểu" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "Kích thước tệp" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "Đã chỉnh sửa" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "Đã tạo" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "tìm thấy" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "và" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "hủy tìm kiếm" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "Xóa" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "hoặc thả tệp của bạn ở đây" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "không có tệp được chọn" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "Tìm kiếm" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "Chọn tệp" + +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/zh-Hans/LC_MESSAGES/django.mo b/filer/locale/zh-Hans/LC_MESSAGES/django.mo new file mode 100644 index 000000000..3ca706516 Binary files /dev/null and b/filer/locale/zh-Hans/LC_MESSAGES/django.mo differ diff --git a/filer/locale/zh-Hans/LC_MESSAGES/django.po b/filer/locale/zh-Hans/LC_MESSAGES/django.po new file mode 100644 index 000000000..20e70e4d0 --- /dev/null +++ b/filer/locale/zh-Hans/LC_MESSAGES/django.po @@ -0,0 +1,1208 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +# Aosp T, 2016-2017 +# node uuz , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-20 10:11+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: node uuz , 2019\n" +"Language-Team: Chinese Simplified (http://app.transifex.com/divio/django-filer/language/zh-Hans/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh-Hans\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: admin/clipboardadmin.py:16 +#| msgid "" +#| "ccount doesn't have permissions to rename all of the selected files." +msgid "You do not have permission to upload files." +msgstr "" + +#: admin/clipboardadmin.py:17 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:19 +msgid "" +"Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:49 +msgid "Advanced" +msgstr "高级" + +#: admin/fileadmin.py:164 +msgid "canonical URL" +msgstr "权威URL" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "要对执行此操作,必须选择项目。没有项目被更改。" + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "选择了 %(total_count)s 个" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "%(folder_name)s文件夹列表" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "选择了 %(cnt)s 中的 0 个" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "没有选择任何动作。" + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "成功将 %(count)d 个文件移动到剪贴板。" + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "移动所选文件到剪贴板" + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "成功禁用了权限设置(%(count)d 个文件)。" + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "成功启用了权限设置(%(count)d 个文件)。" + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "对于所选文件,启用权限设置" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "对于所选文件,禁用权限设置" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "成功删除了 %(count)d 个文件或目录" + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "目录或文件删除失败" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "确定吗?" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "删除文件或目录" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "删除所选的文件或目录" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "所选的位置已存在名为 %s 的目录" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "成功移动 %(count)d 个文件或目录到 '%(destination)s'。" + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "移动目录或文件" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "移动所选的目录或文件" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "成功重命名 %(count)d 个文件。" + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "重命名文件" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "成功将 %(count)d 个文件或目录复制到 '%(destination)s'。" + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "复制文件或目录" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "复制所选的文件或目录" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "成功缩放 %(count)d 个图片。" + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "缩放图片" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "缩放所选的图片" + +#: admin/forms.py:25 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "所复制文件的文件名将会加上后缀。" + +#: admin/forms.py:32 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "后缀应该类似 \"%(valid)s\",是简单、小写的部分文件名称" + +#: admin/forms.py:53 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "未知重命名格式: \"%(key)s\"." + +#: admin/forms.py:55 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "无效的重命名格式:%(error)s 。" + +#: admin/forms.py:69 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "缩略图选项" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "宽" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "高" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "裁剪" + +#: admin/forms.py:76 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "修改分辨率" + +#: admin/forms.py:80 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "必须选择缩略图选项或缩放参数。" + +#: admin/imageadmin.py:18 admin/imageadmin.py:105 +msgid "Subject location" +msgstr "主题位置" + +#: admin/imageadmin.py:19 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "场景中的主题位置。格式:“x,y”。" + +#: admin/imageadmin.py:57 +msgid "Invalid subject location format. " +msgstr "错误的主题位置格式" + +#: admin/imageadmin.py:65 +msgid "Subject location is outside of the image. " +msgstr "主题位置超出了图片范围" + +#: admin/imageadmin.py:74 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "你输入的:\"{subject_location}\"。" + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "这个名称的目录已经存在。" + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "文件管理器" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "媒体库" + +#: models/abstract.py:49 +msgid "default alt text" +msgstr "默认提示文本" + +#: models/abstract.py:56 +msgid "default caption" +msgstr "默认标题" + +#: models/abstract.py:63 +msgid "subject location" +msgstr "主题位置" + +#: models/abstract.py:78 +msgid "image" +msgstr "图片" + +#: models/abstract.py:79 +msgid "images" +msgstr "图片" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "用户" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "文件" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "剪贴板" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "剪贴板" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "文件" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "剪贴板对象" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "剪贴板对象" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "目录" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "文件大小" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "SHA1" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "存在强制性数据" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "原始文件名" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "名称" + +#: models/filemodels.py:116 +msgid "description" +msgstr "描述" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "所有者" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "上传于" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "修改于" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "已禁用权限设置" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "对此文件禁用所有权限设置。此文件将可以被任何人公开访问。" + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "创建于" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "目录" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "目录" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "所有项目" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "仅此项目" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "此项目和所有子项目" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "允许" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "拒绝" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "类型" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "组" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "所有人" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "可读" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "可编辑" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "可增加子项目" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "目录权限" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "目录权限" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "" + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" + +#: models/foldermodels.py:360 +#| msgid "Folders" +msgid "All Folders" +msgstr "" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" + +#: models/foldermodels.py:375 +#| msgid "everybody" +msgid "Everybody" +msgstr "" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +#| msgid "can add children" +msgid "Add children" +msgstr "" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "日期令牌" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "作者" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "必须发布作者信息" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "必须发布版权" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "像素宽度" + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "像素高度" + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "缩略图选项" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:167 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "未分类的上传" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "确实元数据的文件" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "根目录" + +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +#| msgid "thumbnail option" +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "运行所选的动作" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "开始" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:232 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "选择所有页面的对象" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "选择 %(total_count)s 个文件或目录" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:234 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "清空选择" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "回到管理首页" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "首页" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "回到文件管理器首页" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "回到根目录" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "回到 '%(folder_name)s' 目录" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "重复" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "删除所选的文件或目录会将相关的对象同时删除,但是你的账号没有删除下面这些类型对象的权限:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "删除所选的文件或目录会将询问是否删除以下保护对象:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "确认删除所选的文件或目录吗?以下所有相关的对象都会删除:" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "不,返回" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "是的,我确定" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "历史" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "查看站点" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "后退到" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "管理首页" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "目录图标" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files " +"and/or folders." +msgstr "你的账户没有权限复制所有所选的目录或文件。" + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "返回" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "目标目录无效" + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "没有文件或目录可以复制" + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "以下的文件将复制到目标目录(包含它们的树结构):" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "目标目录:" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "复制" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "不允许将文件复制到相同目录" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "你的账号没有权限缩放所有所选的图片。" + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "没有图片可缩放。" + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "以下图片将被缩放:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "选择一个缩略图选项或输入缩放参数:" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "警告:图片将被缩放,并且源文件将被覆盖。你应该先将它们做个备份。" + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "缩放" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files " +"and/or folders." +msgstr "你的账号没有移动所有所选文件或目录的权限。" + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "没有文件或目录可移动。" + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "以下的文件将移动到目标目录(包含它们的树结构):" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "移动" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "不允许将文件移动到相同目录。" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "你的账号没有重命名所有所选文件的权限。" + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "没有文件可重命名。" + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "以下文件将被重命名(源文件不变,只是显示名称被修改而已):" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "重命名" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "回到父目录" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "修改当前目录属性" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "修改" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "点击开始搜索" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "搜索" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "关闭" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "限定" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "将搜索限定在当前目录" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "将搜索限定在当前目录" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "删除" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "新增一个目录" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "新增目录" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "上传文件" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "必须先选择一个目录" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "名称" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:49 +msgid "Owner" +msgstr "所有者" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:33 +msgid "Size" +msgstr "大小" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "动作" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "修改 '%(item_label)s' 目录的属性" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "%(counter)s 个目录" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "%(counter)s 个文件" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "修改目录属性" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "删除目录" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "选择这个文件" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:151 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "修改 '%(item_label)s' 的属性" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "权限" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "禁用" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "激活" + +#: templates/admin/filer/folder/directory_table_list.html:144 +#, python-format +#| msgid "Change '%(item_label)s' details" +msgid "Canonical url '%(item_label)s'" +msgstr "权威URL %(item_label)s" + +#: templates/admin/filer/folder/directory_table_list.html:148 +#, python-format +#| msgid "Change '%(item_label)s' details" +msgid "Download '%(item_label)s'" +msgstr "下载 %(item_label)s" + +#: templates/admin/filer/folder/directory_table_list.html:152 +msgid "Remove file" +msgstr "删除文件" + +#: templates/admin/filer/folder/directory_table_list.html:160 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "拖放文件到这里或使用“上传文件”按钮" + +#: templates/admin/filer/folder/directory_table_list.html:175 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "拖放文件到:" + +#: templates/admin/filer/folder/directory_table_list.html:185 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "上传" + +#: templates/admin/filer/folder/directory_table_list.html:197 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "取消" + +#: templates/admin/filer/folder/directory_table_list.html:201 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "上传成功!" + +#: templates/admin/filer/folder/directory_table_list.html:205 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "取消上传!" + +#: templates/admin/filer/folder/directory_table_list.html:212 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "上一个" + +#: templates/admin/filer/folder/directory_table_list.html:217 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "第 %(number)s 页,共 %(num_pages)s 页" + +#: templates/admin/filer/folder/directory_table_list.html:222 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "下一个" + +#: templates/admin/filer/folder/directory_table_list.html:232 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "选择了 %(total_count)s 个" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +#| msgid "Select this file" +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +#| msgid "Filer" +msgid "Files" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "新增" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "Django 网站管理" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "请更正下面的错误。" + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "保存" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "剪贴板" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "粘贴所有对象到这里" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "移动所有剪贴板文件到" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "清空剪贴板" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "剪贴板是空的" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "上传失败" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:15 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:20 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:107 +#| msgid "file missing" +msgid "File is missing" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:29 +msgid "Type" +msgstr "类型" + +#: templates/admin/filer/tools/detail_info.html:37 +msgid "File-size" +msgstr "文件大小" + +#: templates/admin/filer/tools/detail_info.html:41 +msgid "Modified" +msgstr "修改时间" + +#: templates/admin/filer/tools/detail_info.html:45 +msgid "Created" +msgstr "创建时间" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "已找到" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "与" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "取消搜索" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "清空" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "或在此放入你的文件" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "没选择文件" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "查找" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "选择文件" + +#: templates/admin/filer/widgets/admin_folder.html:16 +#| msgid "Choose File" +msgid "Choose Folder" +msgstr "" + +#: validation.py:19 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" + +#: validation.py:22 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" + +#: validation.py:33 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" + +#: validation.py:71 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/zh/LC_MESSAGES/django.mo b/filer/locale/zh/LC_MESSAGES/django.mo new file mode 100644 index 000000000..1f47492f0 Binary files /dev/null and b/filer/locale/zh/LC_MESSAGES/django.mo differ diff --git a/filer/locale/zh/LC_MESSAGES/django.po b/filer/locale/zh/LC_MESSAGES/django.po new file mode 100644 index 000000000..217dde434 --- /dev/null +++ b/filer/locale/zh/LC_MESSAGES/django.po @@ -0,0 +1,1219 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Angelo Dini \n" +"Language-Team: Chinese (http://app.transifex.com/divio/django-filer/language/" +"zh/)\n" +"Language: zh\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "" + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "" + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "" + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "" + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "" + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "" + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "" + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "" + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "" + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "" + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "" + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "" + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "" + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "" + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "" + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "" + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "" + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "" + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "" + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "" + +#: models/abstract.py:91 +msgid "image" +msgstr "" + +#: models/abstract.py:92 +msgid "images" +msgstr "" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "" + +#: models/filemodels.py:116 +msgid "description" +msgstr "" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "" + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "" + +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:144 +msgid "URL copied to clipboard" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "" + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "" + +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/zh_CN/LC_MESSAGES/django.mo b/filer/locale/zh_CN/LC_MESSAGES/django.mo new file mode 100644 index 000000000..0da366bff Binary files /dev/null and b/filer/locale/zh_CN/LC_MESSAGES/django.mo differ diff --git a/filer/locale/zh_CN/LC_MESSAGES/django.po b/filer/locale/zh_CN/LC_MESSAGES/django.po new file mode 100644 index 000000000..442ac25a4 --- /dev/null +++ b/filer/locale/zh_CN/LC_MESSAGES/django.po @@ -0,0 +1,1219 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Angelo Dini \n" +"Language-Team: Chinese (China) (http://app.transifex.com/divio/django-filer/" +"language/zh_CN/)\n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "" + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "" + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "" + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "" + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "" + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "" + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "" + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "" + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "" + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "" + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "" + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "" + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "" + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "" + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "" + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "" + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "" + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "" + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "" + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "" + +#: models/abstract.py:91 +msgid "image" +msgstr "" + +#: models/abstract.py:92 +msgid "images" +msgstr "" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "" + +#: models/filemodels.py:116 +msgid "description" +msgstr "" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "" + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "" + +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:144 +msgid "URL copied to clipboard" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "" + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "" + +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/locale/zh_TW/LC_MESSAGES/django.mo b/filer/locale/zh_TW/LC_MESSAGES/django.mo new file mode 100644 index 000000000..fdfa81427 Binary files /dev/null and b/filer/locale/zh_TW/LC_MESSAGES/django.mo differ diff --git a/filer/locale/zh_TW/LC_MESSAGES/django.po b/filer/locale/zh_TW/LC_MESSAGES/django.po new file mode 100644 index 000000000..a14b91d38 --- /dev/null +++ b/filer/locale/zh_TW/LC_MESSAGES/django.po @@ -0,0 +1,1219 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Translators: +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django Filer\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-30 18:10+0200\n" +"PO-Revision-Date: 2012-07-13 15:50+0000\n" +"Last-Translator: Angelo Dini \n" +"Language-Team: Chinese (Taiwan) (http://app.transifex.com/divio/django-filer/" +"language/zh_TW/)\n" +"Language: zh_TW\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: admin/clipboardadmin.py:17 +msgid "You do not have permission to upload files." +msgstr "" + +#: admin/clipboardadmin.py:18 +msgid "Can't find folder to upload. Please refresh and try again" +msgstr "" + +#: admin/clipboardadmin.py:20 +msgid "Can't use this folder, Permission Denied. Please select another folder." +msgstr "" + +#: admin/fileadmin.py:73 +msgid "Advanced" +msgstr "" + +#: admin/fileadmin.py:188 +msgid "canonical URL" +msgstr "" + +#: admin/folderadmin.py:411 admin/folderadmin.py:582 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" + +#: admin/folderadmin.py:434 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "" + +#: admin/folderadmin.py:460 +#, python-format +msgid "Directory listing for %(folder_name)s" +msgstr "" + +#: admin/folderadmin.py:475 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "" + +#: admin/folderadmin.py:612 +msgid "No action selected." +msgstr "" + +#: admin/folderadmin.py:664 +#, python-format +msgid "Successfully moved %(count)d files to clipboard." +msgstr "" + +#: admin/folderadmin.py:669 +msgid "Move selected files to clipboard" +msgstr "" + +#: admin/folderadmin.py:709 +#, python-format +msgid "Successfully disabled permissions for %(count)d files." +msgstr "" + +#: admin/folderadmin.py:711 +#, python-format +msgid "Successfully enabled permissions for %(count)d files." +msgstr "" + +#: admin/folderadmin.py:719 +msgid "Enable permissions for selected files" +msgstr "" + +#: admin/folderadmin.py:725 +msgid "Disable permissions for selected files" +msgstr "" + +#: admin/folderadmin.py:789 +#, python-format +msgid "Successfully deleted %(count)d files and/or folders." +msgstr "" + +#: admin/folderadmin.py:794 +msgid "Cannot delete files and/or folders" +msgstr "" + +#: admin/folderadmin.py:796 +msgid "Are you sure?" +msgstr "" + +#: admin/folderadmin.py:802 +msgid "Delete files and/or folders" +msgstr "" + +#: admin/folderadmin.py:823 +msgid "Delete selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:930 +#, python-format +msgid "Folders with names %s already exist at the selected destination" +msgstr "" + +#: admin/folderadmin.py:934 +#, python-format +msgid "" +"Successfully moved %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" + +#: admin/folderadmin.py:942 admin/folderadmin.py:944 +msgid "Move files and/or folders" +msgstr "" + +#: admin/folderadmin.py:959 +msgid "Move selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1016 +#, python-format +msgid "Successfully renamed %(count)d files." +msgstr "" + +#: admin/folderadmin.py:1025 admin/folderadmin.py:1027 +#: admin/folderadmin.py:1042 +msgid "Rename files" +msgstr "" + +#: admin/folderadmin.py:1137 +#, python-format +msgid "" +"Successfully copied %(count)d files and/or folders to folder " +"'%(destination)s'." +msgstr "" + +#: admin/folderadmin.py:1155 admin/folderadmin.py:1157 +msgid "Copy files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1174 +msgid "Copy selected files and/or folders" +msgstr "" + +#: admin/folderadmin.py:1279 +#, python-format +msgid "Successfully resized %(count)d images." +msgstr "" + +#: admin/folderadmin.py:1286 admin/folderadmin.py:1288 +msgid "Resize images" +msgstr "" + +#: admin/folderadmin.py:1303 +msgid "Resize selected images" +msgstr "" + +#: admin/forms.py:24 +msgid "Suffix which will be appended to filenames of copied files." +msgstr "" + +#: admin/forms.py:31 +#, python-format +msgid "" +"Suffix should be a valid, simple and lowercase filename part, like " +"\"%(valid)s\"." +msgstr "" + +#: admin/forms.py:52 +#, python-format +msgid "Unknown rename format value key \"%(key)s\"." +msgstr "" + +#: admin/forms.py:54 +#, python-format +msgid "Invalid rename format: %(error)s." +msgstr "" + +#: admin/forms.py:68 models/thumbnailoptionmodels.py:37 +msgid "thumbnail option" +msgstr "" + +#: admin/forms.py:72 models/thumbnailoptionmodels.py:15 +msgid "width" +msgstr "" + +#: admin/forms.py:73 models/thumbnailoptionmodels.py:20 +msgid "height" +msgstr "" + +#: admin/forms.py:74 models/thumbnailoptionmodels.py:25 +msgid "crop" +msgstr "" + +#: admin/forms.py:75 models/thumbnailoptionmodels.py:30 +msgid "upscale" +msgstr "" + +#: admin/forms.py:79 +msgid "Thumbnail option or resize parameters must be choosen." +msgstr "" + +#: admin/imageadmin.py:20 admin/imageadmin.py:112 +msgid "Subject location" +msgstr "" + +#: admin/imageadmin.py:21 +msgid "Location of the main subject of the scene. Format: \"x,y\"." +msgstr "" + +#: admin/imageadmin.py:59 +msgid "Invalid subject location format. " +msgstr "" + +#: admin/imageadmin.py:67 +msgid "Subject location is outside of the image. " +msgstr "" + +#: admin/imageadmin.py:76 +#, python-brace-format +msgid "Your input: \"{subject_location}\". " +msgstr "" + +#: admin/permissionadmin.py:10 models/foldermodels.py:380 +msgid "Who" +msgstr "" + +#: admin/permissionadmin.py:11 models/foldermodels.py:401 +msgid "What" +msgstr "" + +#: admin/views.py:55 +msgid "Folder with this name already exists." +msgstr "" + +#: apps.py:11 templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/directory_listing.html:33 +msgid "Filer" +msgstr "" + +#: contrib/django_cms/cms_toolbars.py:44 +msgid "Media library" +msgstr "" + +#: models/abstract.py:62 +msgid "default alt text" +msgstr "" + +#: models/abstract.py:69 +msgid "default caption" +msgstr "" + +#: models/abstract.py:76 +msgid "subject location" +msgstr "" + +#: models/abstract.py:91 +msgid "image" +msgstr "" + +#: models/abstract.py:92 +msgid "images" +msgstr "" + +#: models/abstract.py:148 +#, python-format +msgid "" +"Image format not recognized or image size exceeds limit of %(max_pixels)d " +"million pixels by a factor of two or more. Before uploading again, check " +"file format or resize image to %(width)d x %(height)d resolution or lower." +msgstr "" + +#: models/abstract.py:156 +#, python-format +msgid "" +"Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " +"million pixels. Before uploading again, resize image to %(width)d x " +"%(height)d resolution or lower." +msgstr "" + +#: models/clipboardmodels.py:11 models/foldermodels.py:289 +msgid "user" +msgstr "" + +#: models/clipboardmodels.py:17 models/filemodels.py:157 +msgid "files" +msgstr "" + +#: models/clipboardmodels.py:24 models/clipboardmodels.py:50 +msgid "clipboard" +msgstr "" + +#: models/clipboardmodels.py:25 +msgid "clipboards" +msgstr "" + +#: models/clipboardmodels.py:44 models/filemodels.py:74 +#: models/filemodels.py:156 +msgid "file" +msgstr "" + +#: models/clipboardmodels.py:56 +msgid "clipboard item" +msgstr "" + +#: models/clipboardmodels.py:57 +msgid "clipboard items" +msgstr "" + +#: models/filemodels.py:66 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "folder" +msgstr "" + +#: models/filemodels.py:81 +msgid "file size" +msgstr "" + +#: models/filemodels.py:87 +msgid "sha1" +msgstr "" + +#: models/filemodels.py:94 +msgid "has all mandatory data" +msgstr "" + +#: models/filemodels.py:100 +msgid "original filename" +msgstr "" + +#: models/filemodels.py:110 models/foldermodels.py:102 +#: models/thumbnailoptionmodels.py:10 +msgid "name" +msgstr "" + +#: models/filemodels.py:116 +msgid "description" +msgstr "" + +#: models/filemodels.py:125 models/foldermodels.py:108 +msgid "owner" +msgstr "" + +#: models/filemodels.py:129 models/foldermodels.py:116 +msgid "uploaded at" +msgstr "" + +#: models/filemodels.py:134 models/foldermodels.py:126 +msgid "modified at" +msgstr "" + +#: models/filemodels.py:140 +msgid "Permissions disabled" +msgstr "" + +#: models/filemodels.py:141 +msgid "" +"Disable any permission checking for this file. File will be publicly " +"accessible to anyone." +msgstr "" + +#: models/foldermodels.py:94 +msgid "parent" +msgstr "" + +#: models/foldermodels.py:121 +msgid "created at" +msgstr "" + +#: models/foldermodels.py:136 templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Folder" +msgstr "" + +#: models/foldermodels.py:137 +#: templates/admin/filer/folder/directory_thumbnail_list.html:12 +msgid "Folders" +msgstr "" + +#: models/foldermodels.py:260 +msgid "all items" +msgstr "" + +#: models/foldermodels.py:261 +msgid "this item only" +msgstr "" + +#: models/foldermodels.py:262 +msgid "this item and all children" +msgstr "" + +#: models/foldermodels.py:266 +msgid "inherit" +msgstr "" + +#: models/foldermodels.py:267 +msgid "allow" +msgstr "" + +#: models/foldermodels.py:268 +msgid "deny" +msgstr "" + +#: models/foldermodels.py:280 +msgid "type" +msgstr "" + +#: models/foldermodels.py:297 +msgid "group" +msgstr "" + +#: models/foldermodels.py:304 +msgid "everybody" +msgstr "" + +#: models/foldermodels.py:309 +msgid "can read" +msgstr "" + +#: models/foldermodels.py:317 +msgid "can edit" +msgstr "" + +#: models/foldermodels.py:325 +msgid "can add children" +msgstr "" + +#: models/foldermodels.py:333 +msgid "folder permission" +msgstr "" + +#: models/foldermodels.py:334 +msgid "folder permissions" +msgstr "" + +#: models/foldermodels.py:348 +msgid "Folder cannot be selected with type \"all items\"." +msgstr "" + +#: models/foldermodels.py:350 +msgid "Folder has to be selected when type is not \"all items\"." +msgstr "" + +#: models/foldermodels.py:352 +msgid "User or group cannot be selected together with \"everybody\"." +msgstr "" + +#: models/foldermodels.py:354 +msgid "At least one of user, group, or \"everybody\" has to be selected." +msgstr "" + +#: models/foldermodels.py:360 +msgid "All Folders" +msgstr "" + +#: models/foldermodels.py:362 +msgid "Logical Path" +msgstr "" + +#: models/foldermodels.py:371 +#, python-brace-format +msgid "User: {user}" +msgstr "" + +#: models/foldermodels.py:373 +#, python-brace-format +msgid "Group: {group}" +msgstr "" + +#: models/foldermodels.py:375 +msgid "Everybody" +msgstr "" + +#: models/foldermodels.py:388 templates/admin/filer/widgets/admin_file.html:45 +msgid "Edit" +msgstr "" + +#: models/foldermodels.py:389 +msgid "Read" +msgstr "" + +#: models/foldermodels.py:390 +msgid "Add children" +msgstr "" + +#: models/imagemodels.py:18 +msgid "date taken" +msgstr "" + +#: models/imagemodels.py:25 +msgid "author" +msgstr "" + +#: models/imagemodels.py:32 +msgid "must always publish author credit" +msgstr "" + +#: models/imagemodels.py:37 +msgid "must always publish copyright" +msgstr "" + +#: models/thumbnailoptionmodels.py:16 +msgid "width in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:21 +msgid "height in pixel." +msgstr "" + +#: models/thumbnailoptionmodels.py:38 +msgid "thumbnail options" +msgstr "" + +#: models/virtualitems.py:46 +#: templates/admin/filer/folder/directory_table_list.html:4 +#: templates/admin/filer/folder/directory_table_list.html:170 +#: templates/admin/filer/folder/directory_thumbnail_list.html:5 +#: templates/admin/filer/folder/directory_thumbnail_list.html:146 +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Unsorted Uploads" +msgstr "" + +#: models/virtualitems.py:73 +msgid "files with missing metadata" +msgstr "" + +#: models/virtualitems.py:87 templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "root" +msgstr "" + +#: settings.py:273 +msgid "Show table view" +msgstr "" + +#: settings.py:278 +msgid "Show thumbnail view" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Run the selected action" +msgstr "" + +#: templates/admin/filer/actions.html:5 +msgid "Go" +msgstr "" + +#: templates/admin/filer/actions.html:14 +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +msgid "Click here to select the objects across all pages" +msgstr "" + +#: templates/admin/filer/actions.html:14 +#, python-format +msgid "Select all %(total_count)s files and/or folders" +msgstr "" + +#: templates/admin/filer/actions.html:16 +#: templates/admin/filer/folder/directory_table_list.html:237 +#: templates/admin/filer/folder/directory_thumbnail_list.html:212 +msgid "Clear selection" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/directory_listing.html:28 +msgid "Go back to admin homepage" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:4 +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/directory_listing.html:29 +msgid "Home" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:5 +#: templates/admin/filer/folder/directory_listing.html:32 +msgid "Go back to Filer app" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:6 +#: templates/admin/filer/folder/directory_listing.html:35 +msgid "Go back to root folder" +msgstr "" + +#: templates/admin/filer/breadcrumbs.html:8 +#: templates/admin/filer/breadcrumbs.html:18 +#: templates/admin/filer/folder/change_form.html:10 +#: templates/admin/filer/folder/directory_listing.html:39 +#: templates/admin/filer/folder/directory_listing.html:47 +#, python-format +msgid "Go back to '%(folder_name)s' folder" +msgstr "" + +#: templates/admin/filer/change_form.html:26 +msgid "Duplicates" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:11 +msgid "" +"Deleting the selected files and/or folders would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:19 +msgid "" +"Deleting the selected files and/or folders would require deleting the " +"following protected related objects:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:27 +msgid "" +"Are you sure you want to delete the selected files and/or folders? All of " +"the following objects and their related items will be deleted:" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:46 +#: templates/admin/filer/folder/choose_copy_destination.html:64 +#: templates/admin/filer/folder/choose_move_destination.html:72 +msgid "No, take me back" +msgstr "" + +#: templates/admin/filer/delete_selected_files_confirmation.html:47 +msgid "Yes, I'm sure" +msgstr "" + +#: templates/admin/filer/file/change_form.html:35 +#: templates/admin/filer/folder/change_form.html:21 +#: templates/admin/filer/image/change_form.html:35 +msgid "History" +msgstr "" + +#: templates/admin/filer/file/change_form.html:37 +#: templates/admin/filer/folder/change_form.html:23 +#: templates/admin/filer/image/change_form.html:37 +msgid "View on site" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:6 +#: templates/admin/filer/folder/change_form.html:7 +#: templates/admin/filer/folder/change_form.html:8 +#: templates/admin/filer/folder/directory_listing.html:102 +msgid "Go back to" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:6 +msgid "admin homepage" +msgstr "" + +#: templates/admin/filer/folder/change_form.html:37 +#: templates/admin/filer/folder/directory_listing.html:95 +#: templates/admin/filer/folder/directory_listing.html:103 +#: templates/admin/filer/folder/directory_table_list.html:29 +#: templates/admin/filer/folder/directory_table_list.html:59 +#: templates/admin/filer/folder/directory_table_list.html:181 +#: templates/admin/filer/folder/directory_thumbnail_list.html:27 +#: templates/admin/filer/folder/directory_thumbnail_list.html:61 +#: templates/admin/filer/folder/directory_thumbnail_list.html:156 +msgid "Folder Icon" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:23 +msgid "" +"Your account doesn't have permissions to copy all of the selected files and/" +"or folders." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:25 +#: templates/admin/filer/folder/choose_copy_destination.html:31 +#: templates/admin/filer/folder/choose_copy_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:37 +#: templates/admin/filer/folder/choose_move_destination.html:43 +#: templates/admin/filer/folder/choose_move_destination.html:49 +msgid "Take me back" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:29 +#: templates/admin/filer/folder/choose_move_destination.html:41 +msgid "There are no destination folders available." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:35 +msgid "There are no files and/or folders available to copy." +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:40 +msgid "" +"The following files and/or folders will be copied to a destination folder " +"(retaining their tree structure):" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:54 +#: templates/admin/filer/folder/choose_move_destination.html:64 +msgid "Destination folder:" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:65 +#: templates/admin/filer/folder/choose_copy_destination.html:68 +#: templates/admin/filer/folder/directory_listing.html:178 +msgid "Copy" +msgstr "" + +#: templates/admin/filer/folder/choose_copy_destination.html:67 +msgid "It is not allowed to copy files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:15 +msgid "" +"Your account doesn't have permissions to resize all of the selected images." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:18 +msgid "There are no images available to resize." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:20 +msgid "The following images will be resized:" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:32 +msgid "Choose an existing thumbnail option or enter resize parameters:" +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:36 +msgid "" +"Warning: Images will be resized in-place and originals will be lost. Maybe " +"first make a copy of them to retain the originals." +msgstr "" + +#: templates/admin/filer/folder/choose_images_resize_options.html:39 +msgid "Resize" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:35 +msgid "" +"Your account doesn't have permissions to move all of the selected files and/" +"or folders." +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:47 +msgid "There are no files and/or folders available to move." +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:52 +msgid "" +"The following files and/or folders will be moved to a destination folder " +"(retaining their tree structure):" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:73 +#: templates/admin/filer/folder/choose_move_destination.html:76 +#: templates/admin/filer/folder/directory_listing.html:181 +msgid "Move" +msgstr "" + +#: templates/admin/filer/folder/choose_move_destination.html:75 +msgid "It is not allowed to move files into same folder" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:15 +msgid "" +"Your account doesn't have permissions to rename all of the selected files." +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:18 +msgid "There are no files available to rename." +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:20 +msgid "" +"The following files will be renamed (they will stay in their folders and " +"keep original filename, only displayed filename will be changed):" +msgstr "" + +#: templates/admin/filer/folder/choose_rename_format.html:59 +msgid "Rename" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:94 +msgid "Go back to the parent folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change current folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:131 +msgid "Change" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:141 +msgid "Click here to run search for entered phrase" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:144 +msgid "Search" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:151 +msgid "Close" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:153 +msgid "Limit" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:158 +msgid "Check it to limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:159 +msgid "Limit the search to current folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:175 +msgid "Delete" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:203 +msgid "Adds a new Folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:206 +msgid "New Folder" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:211 +#: templates/admin/filer/folder/directory_listing.html:218 +#: templates/admin/filer/folder/directory_listing.html:221 +#: templates/admin/filer/folder/directory_listing.html:228 +#: templates/admin/filer/folder/directory_listing.html:235 +msgid "Upload Files" +msgstr "" + +#: templates/admin/filer/folder/directory_listing.html:233 +msgid "You have to select a folder first" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:16 +msgid "Name" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:17 +#: templates/admin/filer/tools/detail_info.html:50 +msgid "Owner" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:18 +#: templates/admin/filer/tools/detail_info.html:34 +msgid "Size" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:19 +msgid "Action" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:28 +#: templates/admin/filer/folder/directory_table_list.html:35 +#: templates/admin/filer/folder/directory_table_list.html:58 +#: templates/admin/filer/folder/directory_table_list.html:65 +#: templates/admin/filer/folder/directory_thumbnail_list.html:26 +#: templates/admin/filer/folder/directory_thumbnail_list.html:32 +#: templates/admin/filer/folder/directory_thumbnail_list.html:60 +#: templates/admin/filer/folder/directory_thumbnail_list.html:66 +#, python-format +msgid "Change '%(item_label)s' folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:76 +#: templates/admin/filer/tools/search_form.html:5 +#, python-format +msgid "%(counter)s folder" +msgid_plural "%(counter)s folders" +msgstr[0] "" + +#: templates/admin/filer/folder/directory_table_list.html:77 +#: templates/admin/filer/tools/search_form.html:6 +#, python-format +msgid "%(counter)s file" +msgid_plural "%(counter)s files" +msgstr[0] "" + +#: templates/admin/filer/folder/directory_table_list.html:83 +msgid "Change folder details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:84 +msgid "Remove folder" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:96 +#: templates/admin/filer/folder/directory_table_list.html:104 +#: templates/admin/filer/folder/directory_table_list.html:119 +#: templates/admin/filer/folder/directory_thumbnail_list.html:95 +#: templates/admin/filer/folder/directory_thumbnail_list.html:104 +#: templates/admin/filer/folder/directory_thumbnail_list.html:119 +msgid "Select this file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:107 +#: templates/admin/filer/folder/directory_table_list.html:122 +#: templates/admin/filer/folder/directory_table_list.html:154 +#: templates/admin/filer/folder/directory_thumbnail_list.html:107 +#: templates/admin/filer/folder/directory_thumbnail_list.html:122 +#, python-format +msgid "Change '%(item_label)s' details" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "Permissions" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "disabled" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:131 +#: templates/admin/filer/folder/directory_thumbnail_list.html:130 +msgid "enabled" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:144 +msgid "URL copied to clipboard" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:147 +#, python-format +msgid "Canonical url '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:151 +#, python-format +msgid "Download '%(item_label)s'" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:155 +msgid "Remove file" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:163 +#: templates/admin/filer/folder/directory_thumbnail_list.html:138 +msgid "Drop files here or use the \"Upload Files\" button" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:178 +#: templates/admin/filer/folder/directory_thumbnail_list.html:153 +msgid "Drop your file to upload into:" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:188 +#: templates/admin/filer/folder/directory_thumbnail_list.html:163 +msgid "Upload" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:200 +#: templates/admin/filer/folder/directory_thumbnail_list.html:175 +msgid "cancel" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:204 +#: templates/admin/filer/folder/directory_thumbnail_list.html:179 +msgid "Upload success!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:208 +#: templates/admin/filer/folder/directory_thumbnail_list.html:183 +msgid "Upload canceled!" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:215 +#: templates/admin/filer/folder/directory_thumbnail_list.html:190 +msgid "previous" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:220 +#: templates/admin/filer/folder/directory_thumbnail_list.html:195 +#, python-format +msgid "Page %(number)s of %(num_pages)s." +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:225 +#: templates/admin/filer/folder/directory_thumbnail_list.html:200 +msgid "next" +msgstr "" + +#: templates/admin/filer/folder/directory_table_list.html:235 +#: templates/admin/filer/folder/directory_thumbnail_list.html:210 +#, python-format +msgid "Select all %(total_count)s" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:15 +#: templates/admin/filer/folder/directory_thumbnail_list.html:80 +msgid "Select all" +msgstr "" + +#: templates/admin/filer/folder/directory_thumbnail_list.html:77 +msgid "Files" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +#: templates/admin/filer/folder/new_folder_form.html:7 +msgid "Add new" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:4 +msgid "Django site admin" +msgstr "" + +#: templates/admin/filer/folder/new_folder_form.html:15 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "" + +#: templates/admin/filer/folder/new_folder_form.html:30 +msgid "Save" +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:9 +msgid "Your browser does not support audio." +msgstr "" + +#: templates/admin/filer/templatetags/file_icon.html:14 +msgid "Your browser does not support video." +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:9 +msgid "Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:21 +msgid "Paste all items here" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Move all clipboard files to" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:27 +msgid "Empty Clipboard" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard.html:50 +msgid "the clipboard is empty" +msgstr "" + +#: templates/admin/filer/tools/clipboard/clipboard_item_rows.html:16 +msgid "upload failed" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:11 +msgid "Download" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:16 +msgid "Expand" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:21 +#: templates/admin/filer/widgets/admin_file.html:32 +#: templatetags/filer_admin_tags.py:108 +msgid "File is missing" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:30 +msgid "Type" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:38 +msgid "File-size" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:42 +msgid "Modified" +msgstr "" + +#: templates/admin/filer/tools/detail_info.html:46 +msgid "Created" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "found" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:5 +msgid "and" +msgstr "" + +#: templates/admin/filer/tools/search_form.html:7 +msgid "cancel search" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:10 +#: templates/admin/filer/widgets/admin_file.html:39 +#: templates/admin/filer/widgets/admin_folder.html:18 +msgid "Clear" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:22 +msgid "or drop your file here" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:35 +msgid "no file selected" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:50 +#: templates/admin/filer/widgets/admin_folder.html:14 +msgid "Lookup" +msgstr "" + +#: templates/admin/filer/widgets/admin_file.html:51 +msgid "Choose File" +msgstr "" + +#: templates/admin/filer/widgets/admin_folder.html:16 +msgid "Choose Folder" +msgstr "" + +#: validation.py:20 +#, python-brace-format +msgid "File \"{file_name}\": Upload denied by site security policy" +msgstr "" + +#: validation.py:23 +#, python-brace-format +msgid "File \"{file_name}\": {file_type} upload denied by site security policy" +msgstr "" + +#: validation.py:34 +#, python-brace-format +msgid "File \"{file_name}\": HTML upload denied by site security policy" +msgstr "" + +#: validation.py:72 +#, python-brace-format +msgid "" +"File \"{file_name}\": Rejected due to potential cross site scripting " +"vulnerability" +msgstr "" + +#: validation.py:84 +#, python-brace-format +msgid "File \"{file_name}\": SVG file format not recognized" +msgstr "" + +#~ msgid "Resize parameters must be choosen." +#~ msgstr "Resize parameters must be choosen." + +#~ msgid "Choose resize parameters:" +#~ msgstr "Choose resize parameters:" + +#~ msgid "Open file" +#~ msgstr "Open file" + +#~ msgid "Full size preview" +#~ msgstr "Full size preview" + +#~ msgid "Add Description" +#~ msgstr "Add Description" + +#~ msgid "Author" +#~ msgstr "Author" + +#~ msgid "Add Alt-Text" +#~ msgstr "Add Alt-Text" + +#~ msgid "Add caption" +#~ msgstr "Add caption" + +#~ msgid "Add Tags" +#~ msgstr "Add Tags" + +#~ msgid "Change File" +#~ msgstr "Change File" + +#~ msgid "none selected" +#~ msgstr "none selected" + +#~ msgid "Add Folder" +#~ msgstr "Add Folder" + +#~ msgid "Subject Location" +#~ msgstr "Subject location" + +#~ msgid "" +#~ "\n" +#~ " %(counter)s file" +#~ msgid_plural "" +#~ "%(counter)s files\n" +#~ " " +#~ msgstr[0] "15c0f2d28d6dab1af1f6d94906beb627_pl_0" + +#~ msgid "Upload File" +#~ msgstr "Upload File" diff --git a/filer/management/commands/filer_check.py b/filer/management/commands/filer_check.py new file mode 100644 index 000000000..2213de57d --- /dev/null +++ b/filer/management/commands/filer_check.py @@ -0,0 +1,183 @@ +import os + +from django.core.management.base import BaseCommand +from django.utils.module_loading import import_string + +from PIL import UnidentifiedImageError + +from filer import settings as filer_settings +from filer.models.filemodels import File +from filer.utils.loader import load_model + + +class Command(BaseCommand): + help = "Check for orphaned files, missing file references, and set image dimensions." + + def add_arguments(self, parser): + parser.add_argument( + '--orphans', + action='store_true', + dest='orphans', + default=False, + help="Scan media folders for orphaned files.", + ) + parser.add_argument( + '--delete-orphans', + action='store_true', + dest='delete_orphans', + default=False, + help="Delete orphaned files from storage.", + ) + parser.add_argument( + '--missing', + action='store_true', + dest='missing', + default=False, + help="Check file references and report missing files.", + ) + parser.add_argument( + '--delete-missing', + action='store_true', + dest='delete_missing', + default=False, + help="Delete database entries if files are missing in the media folder.", + ) + parser.add_argument( + '--image-dimensions', + action='store_true', + dest='image_dimensions', + default=False, + help="Set image dimensions if they are not set.", + ) + parser.add_argument( + '--noinput', + '--no-input', + action='store_false', + dest='interactive', + default=True, + help="Do not prompt the user for any interactive input.", + ) + + def handle(self, *args, **options): + if options['missing']: + self.verify_references(options) + if options['delete_missing']: + if options['interactive']: + if input( + "\nThis will delete missing file references from the database.\n" + "Type 'yes' to continue, or 'no' to cancel: " + ) != 'yes': + self.stdout.write("Aborted: Missing file references were not deleted.\n") + self.stdout.flush() + return + self.verify_references(options) + + if options['orphans'] or options['delete_orphans']: + if options['delete_orphans'] and options['interactive']: + if input( + "\nThis will delete orphaned files from storage.\n" + "Type 'yes' to continue, or 'no' to cancel: " + ) != 'yes': + self.stdout.write("Aborted: Orphaned files were not deleted.\n") + self.stdout.flush() + return + self.verify_storages(options) + + if options['image_dimensions']: + self.image_dimensions(options) + + def verify_references(self, options): + """ + Checks that every file reference in the database exists in storage. + If a file is missing, either report it or delete the reference based on the provided options. + """ + for file in File.objects.all(): + if not file.file.storage.exists(file.file.name): + if options['delete_missing']: + file.delete() + verbose_msg = f"Deleted missing file reference '{file.folder}/{file}' from the database." + else: + verbose_msg = f"File reference '{file.folder}/{file}' is missing in storage." + if options.get('verbosity', 1) > 2: + self.stdout.write(verbose_msg + "\n") + self.stdout.flush() + elif options.get('verbosity'): + self.stdout.write(os.path.join(str(file.folder), str(file)) + "\n") + self.stdout.flush() + + def verify_storages(self, options): + """ + Scans all storages defined in FILER_STORAGES (e.g., public and private) + for orphaned files, then reports or deletes them based on the options. + """ + + def walk(storage, prefix, label_prefix): + # If the directory does not exist, there is nothing to scan + if not storage.exists(prefix): + return + child_dirs, files = storage.listdir(prefix) + for filename in files: + actual_path = os.path.join(prefix, filename) + relfilename = os.path.join(label_prefix, filename) + if not File.objects.filter(file=actual_path).exists(): + if options['delete_orphans']: + storage.delete(actual_path) + message = f"Deleted orphaned file '{relfilename}'" + else: + message = f"Found orphaned file '{relfilename}'" + if options.get('verbosity', 1) > 2: + self.stdout.write(message + "\n") + self.stdout.flush() + elif options.get('verbosity'): + self.stdout.write(relfilename + "\n") + self.stdout.flush() + for child in child_dirs: + walk(storage, os.path.join(prefix, child), os.path.join(label_prefix, child)) + + # Loop through each storage configuration (e.g., public, private, etc.) + for storage_name, storage_config in filer_settings.FILER_STORAGES.items(): + storage_settings = storage_config.get('main') + if not storage_settings: + continue + storage = import_string(storage_settings['ENGINE'])() + if storage_settings.get('OPTIONS', {}).get('location'): + storage.location = storage_settings['OPTIONS']['location'] + # Set label_prefix: for public and private storages, use their names. + label_prefix = storage_name if storage_name in ['public', 'private'] else storage_settings.get('UPLOAD_TO_PREFIX', '') + walk(storage, storage_settings.get('UPLOAD_TO_PREFIX', ''), label_prefix) + + def image_dimensions(self, options): + """ + For images without set dimensions (_width == 0 or None), try to read their dimensions + and save them, handling SVG files and possible image errors. + """ + from django.db.models import Q + + import easy_thumbnails + from easy_thumbnails.VIL import Image as VILImage + + from filer.utils.compatibility import PILImage + + ImageModel = load_model(filer_settings.FILER_IMAGE_MODEL) + images_without_dimensions = ImageModel.objects.filter(Q(_width=0) | Q(_width__isnull=True)) + self.stdout.write(f"Setting dimensions for {images_without_dimensions.count()} images" + "\n") + self.stdout.flush() + for image in images_without_dimensions: + file_holder = image.file_ptr if getattr(image, 'file_ptr', None) else image + try: + imgfile = file_holder.file + imgfile.seek(0) + except FileNotFoundError: + continue + if image.file.name.lower().endswith('.svg'): + # For SVG files, use VILImage (invalid SVGs do not throw errors) + with VILImage.load(imgfile) as vil_image: + image._width, image._height = vil_image.size + else: + try: + with PILImage.open(imgfile) as pil_image: + image._width, image._height = pil_image.size + image._transparent = easy_thumbnails.utils.is_transparent(pil_image) + except UnidentifiedImageError: + continue + image.save() diff --git a/filer/management/commands/files_status.py b/filer/management/commands/files_status.py new file mode 100644 index 000000000..fa1f7a4c5 --- /dev/null +++ b/filer/management/commands/files_status.py @@ -0,0 +1,48 @@ +from django.contrib.sites.models import Site +from django.core.management.base import BaseCommand +# makes sure cms is loaded first +# import cms +from filer.utils.status import FileChecker + + +class Command(BaseCommand): + + help = "Checks wheather filer files exist on storage." + + def add_arguments(self, parser): + # Named (optional) arguments + parser.add_argument( + '--site_id', + action='store', + dest='site_id', + type=int, + help='Site Id' + ) + + def handle(self, *args, **options): + self.stdout.write( + "Checking filer files. This might take a while...\n") + + every = 50 + times = 0 + + def logger(stats): + logger.times += 1 + if logger.times % every == 0: + self.stdout.write("\n" + stats.progress()) + logger.times = 0 + + site_id = options['site_id'] + if site_id: + self.stdout.write(f'The site id is: {site_id}.') + try: + _ = Site.objects.get(pk=site_id) + except Site.DoesNotExist: + self.stdout.write(f'The site with id {site_id} does not exist.') + return + + result_stats = FileChecker.check_site(site_id, log_progress=logger) + self.stdout.write(result_stats.as_string(full=True)) + else: + result_stats = FileChecker.check_all(log_progress=logger) + self.stdout.write(result_stats.as_string(full=True)) diff --git a/filer/management/commands/fixfoldertrees.py b/filer/management/commands/fixfoldertrees.py new file mode 100644 index 000000000..947eb57b5 --- /dev/null +++ b/filer/management/commands/fixfoldertrees.py @@ -0,0 +1,62 @@ +from django.core.management.base import BaseCommand +from filer.utils.checktrees import TreeChecker, TreeCorruption + + +class Command(BaseCommand): + + help = "Fixes the folder mptt tree hierarchy (tree corruption)." + + def add_arguments(self, parser): + parser.add_argument('--check', + action='store_true', + dest='checktree', + default=False, + help='Performs only a check for corrupted folder trees. ' + 'Prints all the corruptions it finds.') + parser.add_argument('--force-rebuild', + action='store_true', + dest='force_full_rebuild', + default=False, + help='Force a full tree rebuild.') + + def handle(self, *args, **options): + checker = TreeChecker() + if options['checktree']: + try: + self.stdout.write("Checking folder trees...\n") + checker.find_corruptions() + except TreeCorruption: + if checker.full_rebuild: + self.stdout.write( + 'There are multiple root folders with the same ' + 'tree_id. This will require a full rebuild.\n') + else: + for folder_pk, msg in list(checker.corrupted_folders.items()): + self.stdout.write('Folder /%s:\n\t%s' % ( + checker._get_folder_path(folder_pk), msg)) + self.stdout.write('\n') + self.stdout.write( + "\nFollowing trees will require a rebuild\n") + for folder in checker.get_corrupted_root_nodes(): + self.stdout.write('\n/%s' % folder.name) + self.stdout.write('\n') + else: + self.stdout.write("There are no corruptions\n") + else: + if options['force_full_rebuild']: + self.stdout.write("\nPerforming full rebuild...") + checker.manager.rebuild() + else: + self.stdout.write("Checking folder trees before fixing...\n") + checker.check_corruptions() + if checker.full_rebuild: + self.stdout.write("\nPerforming full rebuild...") + checker.manager.rebuild() + elif checker.corrupted_folders: + self.stdout.write("\nPerforming corrupted folders rebuild...") + for folder in checker.get_corrupted_root_nodes(): + self.stdout.write(f"\n\tPerforming partial rebuild for folder {folder.name}") + checker.manager.partial_rebuild(folder.tree_id) + else: + self.stdout.write("There are no corruptions, nothing to be done.\n") + self.stdout.write("\nRebuild Done.") diff --git a/filer/management/commands/generate_thumbnails.py b/filer/management/commands/generate_thumbnails.py new file mode 100644 index 000000000..64bf3df2f --- /dev/null +++ b/filer/management/commands/generate_thumbnails.py @@ -0,0 +1,28 @@ +from django.core.management.base import BaseCommand + +from filer.models.imagemodels import Image + + +class Command(BaseCommand): + + def handle(self, *args, **options): + """ + Generates image thumbnails + + NOTE: To keep memory consumption stable avoid iteration over the Image queryset + """ + pks = Image.objects.all().values_list('id', flat=True) + total = len(pks) + for idx, pk in enumerate(pks): + image = None + try: + image = Image.objects.get(pk=pk) + self.stdout.write(u'Processing image {0} / {1} {2}'.format(idx + 1, total, image)) + self.stdout.flush() + image.thumbnails + image.icons + except IOError as e: + self.stderr.write('Failed to generate thumbnails: {0}'.format(str(e))) + self.stderr.flush() + finally: + del image diff --git a/filer/management/commands/import_files.py b/filer/management/commands/import_files.py index 625d87280..edc65b0ff 100644 --- a/filer/management/commands/import_files.py +++ b/filer/management/commands/import_files.py @@ -1,11 +1,10 @@ #-*- coding: utf-8 -*- from django.core.files import File as DjangoFile -from django.core.management.base import BaseCommand, NoArgsCommand +from django.core.management.base import BaseCommand, CommandError from filer.models.filemodels import File from filer.models.foldermodels import Folder from filer.models.imagemodels import Image from filer.settings import FILER_IS_PUBLIC_DEFAULT -from optparse import make_option import os @@ -43,9 +42,9 @@ def import_file(self, file_obj, folder): if created: self.file_created += 1 if self.verbosity >= 2: - print u"file_created #%s / image_created #%s -- file : %s -- created : %s" % (self.file_created, + print("file_created #%s / image_created #%s -- file : %s -- created : %s" % (self.file_created, self.image_created, - obj, created) + obj, created)) return obj def get_or_create_folder(self, folder_names): @@ -66,8 +65,8 @@ def get_or_create_folder(self, folder_names): if created: self.folder_created += 1 if self.verbosity >= 2: - print u"folder_created #%s folder : %s -- created : %s" % (self.folder_created, - current_parent, created) + print("folder_created #%s folder : %s -- created : %s" % (self.folder_created, + current_parent, created)) return current_parent def walker(self, path=None, base_folder=None): @@ -80,12 +79,12 @@ def walker(self, path=None, base_folder=None): # prevent trailing slashes and other inconsistencies on path. # cast to unicode so that os.walk returns path names in unicode # (prevents encoding/decoding errors) - path = unicode(os.path.normpath(path)) + path = str(os.path.normpath(path)) if base_folder: - base_folder = unicode(os.path.normpath(base_folder)) - print u"The directory structure will be imported in %s" % (base_folder,) + base_folder = str(os.path.normpath(base_folder)) + print("The directory structure will be imported in %s" % (base_folder,)) if self.verbosity >= 1: - print u"Import the folders and files in %s" % (path,) + print("Import the folders and files in %s" % (path,)) root_folder_name = os.path.basename(path) for root, dirs, files in os.walk(path): rel_folders = root.partition(path)[2].strip(os.path.sep).split(os.path.sep) @@ -101,13 +100,13 @@ def walker(self, path=None, base_folder=None): name=file_obj) self.import_file(file_obj=dj_file, folder=folder) if self.verbosity >= 1: - print ('folder_created #%s / file_created #%s / ' + \ + print(('folder_created #%s / file_created #%s / ' + \ 'image_created #%s') % ( self.folder_created, self.file_created, - self.image_created) + self.image_created)) -class Command(NoArgsCommand): +class Command(BaseCommand): """ Import directory structure into the filer :: @@ -115,19 +114,28 @@ class Command(NoArgsCommand): manage.py --path=/tmp/assets/news --folder=images """ - option_list = BaseCommand.option_list + ( - make_option('--path', + def add_arguments(self, parser): + parser.add_argument('--path', action='store', dest='path', default=False, - help='Import files located in the path into django-filer'), - make_option('--folder', + help='Import files located in the path into django-filer') + parser.add_argument('--folder', action='store', dest='base_folder', default=False, - help='Specify the destination folder in which the directory structure should be imported'), - ) + help='Specify the destination folder in which the directory structure should be imported') - def handle_noargs(self, **options): + def handle(self, *args, **options): + if args: + raise CommandError( + "This command does not accept positional arguments. " + "Use --path and --folder options instead." + ) + if not options.get('path'): + raise CommandError( + "The --path option is required. " + "Use --path to specify the directory to import." + ) file_importer = FileImporter(**options) file_importer.walker() diff --git a/filer/management/commands/take_out_filer_trash.py b/filer/management/commands/take_out_filer_trash.py new file mode 100644 index 000000000..ea96bc0c2 --- /dev/null +++ b/filer/management/commands/take_out_filer_trash.py @@ -0,0 +1,46 @@ +from django.core.management.base import BaseCommand +from filer.models import File, Folder +from filer import settings as filer_settings +from django.utils import timezone +from datetime import timedelta + + +class Command(BaseCommand): + + help = "Hard-deletes old files and folders from filer trash." + + def handle(self, *args, **options): + no_of_sec = filer_settings.FILER_TRASH_CLEAN_INTERVAL + time_threshold = timezone.now() - timedelta(seconds=no_of_sec) + files_ids = File.trash.filter(deleted_at__lt=time_threshold)\ + .values_list('id', flat=True) + folder_ids = Folder.trash.filter(deleted_at__lt=time_threshold)\ + .order_by('tree_id', '-level').values_list('id', flat=True) + + if not folder_ids and not files_ids: + self.stdout.write("No old files or folders.\n") + return + + for file_id in files_ids: + a_file = File.trash.get(id=file_id) + self.stdout.write("Deleting file %s: %s\n" % ( + file_id, repr(a_file.file.name))) + try: + a_file.delete(to_trash=False) + except Exception as e: + self.stderr.write("%s\n" % str(e)) + + for folder_id in folder_ids: + a_folder = Folder.trash.get(id=folder_id) + ancestors = a_folder.get_ancestors(include_self=True) + path = repr('/'.join(ancestors.values_list('name', flat=True))) + if File.all_objects.filter(folder=folder_id).exists(): + self.stdout.write("Cannot delete folder %s: %s since is " + "not empty.\n" % (folder_id, path)) + continue + self.stdout.write( + "Deleting folder %s: %s\n" % (folder_id, path)) + try: + a_folder.delete(to_trash=False) + except Exception as e: + self.stderr.write("%s\n" % str(e)) diff --git a/filer/migrations/0001_initial.py b/filer/migrations/0001_initial.py index 97b7f2aa2..0a04f5318 100644 --- a/filer/migrations/0001_initial.py +++ b/filer/migrations/0001_initial.py @@ -1,213 +1,163 @@ +# -*- coding: utf-8 -*- -from south.db import db -from django.db import models -from filer.models import * -class Migration: - - def forwards(self, orm): - - # Adding model 'Image' - db.create_table('filer_image', ( - ('file_ptr', orm['filer.Image:file_ptr']), - ('_height', orm['filer.Image:_height']), - ('_width', orm['filer.Image:_width']), - ('date_taken', orm['filer.Image:date_taken']), - ('default_alt_text', orm['filer.Image:default_alt_text']), - ('default_caption', orm['filer.Image:default_caption']), - ('author', orm['filer.Image:author']), - ('must_always_publish_author_credit', orm['filer.Image:must_always_publish_author_credit']), - ('must_always_publish_copyright', orm['filer.Image:must_always_publish_copyright']), - ('subject_location', orm['filer.Image:subject_location']), - )) - db.send_create_signal('filer', ['Image']) - - # Adding model 'ClipboardItem' - db.create_table('filer_clipboarditem', ( - ('id', orm['filer.ClipboardItem:id']), - ('file', orm['filer.ClipboardItem:file']), - ('clipboard', orm['filer.ClipboardItem:clipboard']), - )) - db.send_create_signal('filer', ['ClipboardItem']) - - # Adding model 'File' - db.create_table('filer_file', ( - ('id', orm['filer.File:id']), - ('folder', orm['filer.File:folder']), - ('file_field', orm['filer.File:file_field']), - ('_file_type_plugin_name', orm['filer.File:_file_type_plugin_name']), - ('_file_size', orm['filer.File:_file_size']), - ('has_all_mandatory_data', orm['filer.File:has_all_mandatory_data']), - ('original_filename', orm['filer.File:original_filename']), - ('name', orm['filer.File:name']), - ('owner', orm['filer.File:owner']), - ('uploaded_at', orm['filer.File:uploaded_at']), - ('modified_at', orm['filer.File:modified_at']), - )) - db.send_create_signal('filer', ['File']) - - # Adding model 'Folder' - db.create_table('filer_folder', ( - ('id', orm['filer.Folder:id']), - ('parent', orm['filer.Folder:parent']), - ('name', orm['filer.Folder:name']), - ('owner', orm['filer.Folder:owner']), - ('uploaded_at', orm['filer.Folder:uploaded_at']), - ('created_at', orm['filer.Folder:created_at']), - ('modified_at', orm['filer.Folder:modified_at']), - ('lft', orm['filer.Folder:lft']), - ('rght', orm['filer.Folder:rght']), - ('tree_id', orm['filer.Folder:tree_id']), - ('level', orm['filer.Folder:level']), - )) - db.send_create_signal('filer', ['Folder']) - - # Adding model 'Clipboard' - db.create_table('filer_clipboard', ( - ('id', orm['filer.Clipboard:id']), - ('user', orm['filer.Clipboard:user']), - )) - db.send_create_signal('filer', ['Clipboard']) - - # Adding model 'FolderPermission' - db.create_table('filer_folderpermission', ( - ('id', orm['filer.FolderPermission:id']), - ('folder', orm['filer.FolderPermission:folder']), - ('type', orm['filer.FolderPermission:type']), - ('user', orm['filer.FolderPermission:user']), - ('group', orm['filer.FolderPermission:group']), - ('everybody', orm['filer.FolderPermission:everybody']), - ('can_edit', orm['filer.FolderPermission:can_edit']), - ('can_read', orm['filer.FolderPermission:can_read']), - ('can_add_children', orm['filer.FolderPermission:can_add_children']), - )) - db.send_create_signal('filer', ['FolderPermission']) - - # Creating unique_together for [parent, name] on Folder. - db.create_unique('filer_folder', ['parent_id', 'name']) - - - - def backwards(self, orm): - - # Deleting unique_together for [parent, name] on Folder. - db.delete_unique('filer_folder', ['parent_id', 'name']) - - # Deleting model 'Image' - db.delete_table('filer_image') - - # Deleting model 'ClipboardItem' - db.delete_table('filer_clipboarditem') - - # Deleting model 'File' - db.delete_table('filer_file') - - # Deleting model 'Folder' - db.delete_table('filer_folder') - - # Deleting model 'Clipboard' - db.delete_table('filer_clipboard') - - # Deleting model 'FolderPermission' - db.delete_table('filer_folderpermission') - - - - models = { - 'auth.group': { - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'unique_together': "(('content_type', 'codename'),)"}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'unique_together': "(('app_label', 'model'),)", 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'filer.clipboard': { - 'files': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['filer.File']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'clipboards'", 'to': "orm['auth.User']"}) - }, - 'filer.clipboarditem': { - 'clipboard': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.Clipboard']"}), - 'file': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.File']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) - }, - 'filer.file': { - '_file_size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - '_file_type_plugin_name': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'file_field': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'folder': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'all_files'", 'null': 'True', 'to': "orm['filer.Folder']"}), - 'has_all_mandatory_data': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'original_filename': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'owned_files'", 'null': 'True', 'to': "orm['auth.User']"}), - 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) - }, - 'filer.folder': { - 'Meta': {'unique_together': "(('parent', 'name'),)"}, - 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'owned_folders'", 'null': 'True', 'to': "orm['auth.User']"}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['filer.Folder']"}), - 'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) - }, - 'filer.folderpermission': { - 'can_add_children': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), - 'can_edit': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), - 'can_read': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), - 'everybody': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'folder': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.Folder']", 'null': 'True', 'blank': 'True'}), - 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.Group']", 'null': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'type': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}) - }, - 'filer.image': { - '_height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - '_width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'author': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'date_taken': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'default_alt_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'default_caption': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'file_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['filer.File']", 'unique': 'True', 'primary_key': 'True'}), - 'must_always_publish_author_credit': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'must_always_publish_copyright': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'subject_location': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '64', 'null': 'True', 'blank': 'True'}) - } - } - - complete_apps = ['filer'] +from django.db import models, migrations +import filer.fields.multistorage_file +import filer.models.mixins +import django.db.models.deletion +from django.conf import settings + + +class Migration(migrations.Migration): + + dependencies = [ + ('sites', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('contenttypes', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='Clipboard', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ], + options={ + 'verbose_name': 'clipboard', + 'verbose_name_plural': 'clipboards', + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='ClipboardItem', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('clipboard', models.ForeignKey(verbose_name='clipboard', to='filer.Clipboard', on_delete=models.CASCADE)), + ], + options={ + 'verbose_name': 'clipboard item', + 'verbose_name_plural': 'clipboard items', + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='File', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('file', filer.fields.multistorage_file.MultiStorageFileField(upload_to=filer.fields.multistorage_file.generate_filename_multistorage, max_length=255, blank=True, null=True, verbose_name='file', db_index=True)), + ('_file_size', models.IntegerField(null=True, verbose_name='file size', blank=True)), + ('sha1', models.CharField(default='', max_length=40, verbose_name='sha1', blank=True)), + ('has_all_mandatory_data', models.BooleanField(default=False, verbose_name='has all mandatory data', editable=False)), + ('original_filename', models.CharField(max_length=255, null=True, verbose_name='original filename', blank=True)), + ('name', models.CharField(help_text='Change the FILE name for an image in the cloud storage system; be sure to include the extension (.jpg or .png, for example) to ensure asset remains valid.', max_length=255, null=True, verbose_name='file name', blank=True)), + ('title', models.CharField(help_text='Used in the Photo Gallery plugin as a title or name for an image; not displayed via the image plugin.', max_length=255, null=True, verbose_name='name', blank=True)), + ('description', models.TextField(help_text='Used in the Photo Gallery plugin as a description; not displayed via the image plugin.', null=True, verbose_name='description', blank=True)), + ('uploaded_at', models.DateTimeField(auto_now_add=True, verbose_name='uploaded at')), + ('modified_at', models.DateTimeField(auto_now=True, verbose_name='modified at')), + ('is_public', models.BooleanField(default=True, help_text='Disable any permission checking for this file. File will be publicly accessible to anyone.', verbose_name='Permissions disabled')), + ('restricted', models.BooleanField(default=False, help_text='If this box is checked, Editors and Writers will still be able to view the asset, add it to a plugin or smart snippet but will not be able to delete or modify the current version of the asset.', verbose_name='Restrict Editors and Writers from being able to edit or delete this asset')), + ('deleted_at', models.DateTimeField(verbose_name='deleted at', null=True, editable=False, blank=True)), + ], + options={ + 'verbose_name': 'file', + 'verbose_name_plural': 'files', + }, + bases=(models.Model, filer.models.mixins.IconsMixin), + ), + migrations.CreateModel( + name='Archive', + fields=[ + ('file_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='filer.File', on_delete=django.db.models.deletion.CASCADE)), + ], + options={ + 'verbose_name': 'archive', + 'verbose_name_plural': 'archives', + }, + bases=('filer.file',), + ), + migrations.CreateModel( + name='Folder', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('name', models.CharField(max_length=255, verbose_name='name')), + ('uploaded_at', models.DateTimeField(auto_now_add=True, verbose_name='uploaded at')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='created at')), + ('modified_at', models.DateTimeField(auto_now=True, verbose_name='modified at')), + ('folder_type', models.IntegerField(default=0, choices=[(0, 'Site Folder'), (1, 'Core Folder')])), + ('restricted', models.BooleanField(default=False, help_text='If this box is checked, Editors and Writers will still be able to view this folder assets, add them to a plugin or smart snippet but will not be able to delete or modify the current version of the assets.', verbose_name='Restrict Editors and Writers from being able to edit or delete anything from this folder')), + ('deleted_at', models.DateTimeField(verbose_name='deleted at', null=True, editable=False, blank=True)), + ('lft', models.PositiveIntegerField(editable=False, db_index=True)), + ('rght', models.PositiveIntegerField(editable=False, db_index=True)), + ('tree_id', models.PositiveIntegerField(editable=False, db_index=True)), + ('level', models.PositiveIntegerField(editable=False, db_index=True)), + ('owner', models.ForeignKey(related_name='filer_owned_folders', on_delete=django.db.models.deletion.SET_NULL, verbose_name='owner', blank=True, to=settings.AUTH_USER_MODEL, null=True)), + ('parent', models.ForeignKey(related_name='children', verbose_name='parent', blank=True, to='filer.Folder', null=True, on_delete=django.db.models.deletion.CASCADE)), + ('shared', models.ManyToManyField(related_name='shared', to='sites.Site', blank=True, help_text='All the sites which you share this folder with will be able to use this folder on their pages, with all of its assets. However, they will not be able to change, delete or move it, not even add new assets.', null=True, verbose_name='Share folder with sites')), + ('site', models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, blank=True, to='sites.Site', help_text='Select the site which will use this folder.', null=True)), + ], + options={ + 'ordering': ('name',), + 'verbose_name': 'Folder', + 'verbose_name_plural': 'Folders', + 'permissions': (('can_use_directory_listing', 'Can use directory listing'), ('can_restrict_operations', 'Can restrict files or folders')), + }, + bases=(models.Model, filer.models.mixins.IconsMixin), + ), + migrations.CreateModel( + name='Image', + fields=[ + ('file_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='filer.File', on_delete=django.db.models.deletion.CASCADE)), + ('_height', models.IntegerField(null=True, blank=True)), + ('_width', models.IntegerField(null=True, blank=True)), + ('date_taken', models.DateTimeField(verbose_name='date taken', null=True, editable=False, blank=True)), + ('default_alt_text', models.CharField(help_text='Describes the essence of the image for users who have images turned off in their browser, or are visually impaired and using a screen reader; and it is used to identify images to search engines.', max_length=255, null=True, verbose_name='default alt text', blank=True)), + ('default_caption', models.CharField(help_text='Caption text is displayed directly below an image plugin to add context; there is a 140-character limit, including spaces; for images fewer than 200 pixels wide, the caption text is only displayed on hover.', max_length=255, null=True, verbose_name='default caption', blank=True)), + ('default_credit', models.CharField(help_text='Credit text gives credit to the owner or licensor of an image; it is displayed below the image plugin, or below the caption text on an image plugin, if that option is selected; it is displayed along the bottom of an image in the photo gallery plugin; there is a 30-character limit, including spaces.', max_length=255, null=True, verbose_name='default credit text', blank=True)), + ('author', models.CharField(max_length=255, null=True, verbose_name='author', blank=True)), + ('must_always_publish_author_credit', models.BooleanField(default=False, verbose_name='must always publish author credit')), + ('must_always_publish_copyright', models.BooleanField(default=False, verbose_name='must always publish copyright')), + ('subject_location', models.CharField(default=None, max_length=64, null=True, verbose_name='subject location', blank=True)), + ], + options={ + 'verbose_name': 'image', + 'verbose_name_plural': 'images', + }, + bases=('filer.file',), + ), + migrations.AddField( + model_name='file', + name='folder', + field=models.ForeignKey(related_name='all_files', verbose_name='folder', blank=True, to='filer.Folder', on_delete=django.db.models.deletion.CASCADE, null=True), + preserve_default=True, + ), + migrations.AddField( + model_name='file', + name='owner', + field=models.ForeignKey(related_name='owned_files', on_delete=django.db.models.deletion.CASCADE, verbose_name='uploaded by', blank=True, to=settings.AUTH_USER_MODEL, null=True), + preserve_default=True, + ), + migrations.AddField( + model_name='file', + name='polymorphic_ctype', + field=models.ForeignKey(related_name='polymorphic_filer.file_set+', on_delete=django.db.models.deletion.CASCADE, editable=False, to='contenttypes.ContentType', null=True), + preserve_default=True, + ), + migrations.AddField( + model_name='clipboarditem', + name='file', + field=models.ForeignKey(verbose_name='file', to='filer.File', on_delete=django.db.models.deletion.CASCADE), + preserve_default=True, + ), + migrations.AddField( + model_name='clipboard', + name='files', + field=models.ManyToManyField(related_name='in_clipboards', verbose_name='files', through='filer.ClipboardItem', to='filer.File'), + preserve_default=True, + ), + migrations.AddField( + model_name='clipboard', + name='user', + field=models.ForeignKey(related_name='filer_clipboards', verbose_name='user', to=settings.AUTH_USER_MODEL, on_delete=django.db.models.deletion.CASCADE), + preserve_default=True, + ), + ] diff --git a/filer/migrations/0002_auto_20150928_1109.py b/filer/migrations/0002_auto_20150928_1109.py new file mode 100644 index 000000000..d473ed028 --- /dev/null +++ b/filer/migrations/0002_auto_20150928_1109.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- + + +from django.db import models, migrations +import django.db.models.deletion +from django.conf import settings + + +class Migration(migrations.Migration): + + dependencies = [ + ('filer', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='file', + name='owner', + field=models.ForeignKey(related_name='owned_files', on_delete=django.db.models.deletion.SET_NULL, verbose_name='owner', blank=True, to=settings.AUTH_USER_MODEL, null=True), + ), + migrations.AlterField( + model_name='folder', + name='shared', + field=models.ManyToManyField(help_text='All the sites which you share this folder with will be able to use this folder on their pages, with all of its assets. However, they will not be able to change, delete or move it, not even add new assets.', related_name='shared', verbose_name='Share folder with sites', to='sites.Site', blank=True), + ), + ] diff --git a/filer/migrations/0002_rename_file_field.py b/filer/migrations/0002_rename_file_field.py deleted file mode 100644 index ac0060814..000000000 --- a/filer/migrations/0002_rename_file_field.py +++ /dev/null @@ -1,118 +0,0 @@ - -from south.db import db -from django.db import models -from filer.models import * - -class Migration: - - def forwards(self, orm): - - # rename the file field - db.rename_column('filer_file', 'file_field', '_file') - - - - def backwards(self, orm): - - db.rename_column('filer_file', '_file', 'file_field') - - - - models = { - 'auth.group': { - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'unique_together': "(('content_type', 'codename'),)"}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'unique_together': "(('app_label', 'model'),)", 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'filer.clipboard': { - 'files': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['filer.File']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'clipboards'", 'to': "orm['auth.User']"}) - }, - 'filer.clipboarditem': { - 'clipboard': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.Clipboard']"}), - 'file': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.File']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) - }, - 'filer.file': { - '_file': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - '_file_size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - '_file_type_plugin_name': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'folder': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'all_files'", 'null': 'True', 'to': "orm['filer.Folder']"}), - 'has_all_mandatory_data': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'original_filename': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'owned_files'", 'null': 'True', 'to': "orm['auth.User']"}), - 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) - }, - 'filer.folder': { - 'Meta': {'unique_together': "(('parent', 'name'),)"}, - 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'owned_folders'", 'null': 'True', 'to': "orm['auth.User']"}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['filer.Folder']"}), - 'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) - }, - 'filer.folderpermission': { - 'can_add_children': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), - 'can_edit': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), - 'can_read': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), - 'everybody': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'folder': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.Folder']", 'null': 'True', 'blank': 'True'}), - 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.Group']", 'null': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'type': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}) - }, - 'filer.image': { - '_height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - '_width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'author': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'date_taken': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'default_alt_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'default_caption': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'file_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['filer.File']", 'unique': 'True', 'primary_key': 'True'}), - 'must_always_publish_author_credit': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'must_always_publish_copyright': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'subject_location': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '64', 'null': 'True', 'blank': 'True'}) - } - } - - complete_apps = ['filer'] diff --git a/filer/migrations/0003_add_description_field.py b/filer/migrations/0003_add_description_field.py deleted file mode 100644 index 3a6b43e35..000000000 --- a/filer/migrations/0003_add_description_field.py +++ /dev/null @@ -1,120 +0,0 @@ - -from south.db import db -from django.db import models -from filer.models import * - -class Migration: - - def forwards(self, orm): - - # Adding field 'File.description' - db.add_column('filer_file', 'description', orm['filer.file:description']) - - - - def backwards(self, orm): - - # Deleting field 'File.description' - db.delete_column('filer_file', 'description') - - - - models = { - 'auth.group': { - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'unique_together': "(('content_type', 'codename'),)"}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'unique_together': "(('app_label', 'model'),)", 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'filer.clipboard': { - 'files': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['filer.File']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'filer_clipboards'", 'to': "orm['auth.User']"}) - }, - 'filer.clipboarditem': { - 'clipboard': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.Clipboard']"}), - 'file': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.File']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) - }, - 'filer.file': { - '_file': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - '_file_size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - '_file_type_plugin_name': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'folder': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'all_files'", 'null': 'True', 'to': "orm['filer.Folder']"}), - 'has_all_mandatory_data': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'original_filename': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'owned_files'", 'null': 'True', 'to': "orm['auth.User']"}), - 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) - }, - 'filer.folder': { - 'Meta': {'unique_together': "(('parent', 'name'),)"}, - 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_owned_folders'", 'null': 'True', 'to': "orm['auth.User']"}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['filer.Folder']"}), - 'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) - }, - 'filer.folderpermission': { - 'can_add_children': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), - 'can_edit': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), - 'can_read': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), - 'everybody': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'folder': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.Folder']", 'null': 'True', 'blank': 'True'}), - 'group': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_folder_permissions'", 'null': 'True', 'to': "orm['auth.Group']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'type': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_folder_permissions'", 'null': 'True', 'to': "orm['auth.User']"}) - }, - 'filer.image': { - '_height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - '_width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'author': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'date_taken': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'default_alt_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'default_caption': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'file_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['filer.File']", 'unique': 'True', 'primary_key': 'True'}), - 'must_always_publish_author_credit': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'must_always_publish_copyright': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'subject_location': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '64', 'null': 'True', 'blank': 'True'}) - } - } - - complete_apps = ['filer'] diff --git a/filer/migrations/0003_delete_duplicate_clipboards.py b/filer/migrations/0003_delete_duplicate_clipboards.py new file mode 100644 index 000000000..7dfa13e63 --- /dev/null +++ b/filer/migrations/0003_delete_duplicate_clipboards.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- + + +from django.db import models, migrations + + +def delete_extra_clipboards(apps, schema_editor): + """ + Delete duplicate clipboards (keep the one with the most files) so a unique + user constraint can be added. + """ + User = apps.get_model("auth", "User") + + users = (User.objects.all() + .annotate(nr_clipboards=models.Count('filer_clipboards')) + .filter(nr_clipboards__gt=1)) + + if not users: + print("Nobody has more than one clipboard. Nothing to do here.") + return + + for user in users: + clipboards = user.filer_clipboards.all() + print("Removing duplicate clipboards for {}, id {} (has {})".format( + user, user.id, len(clipboards))) + clipboard_to_stay = max(clipboards, key=lambda c: c.clipboarditem_set.all().count()) + for clipboard in clipboards: + if clipboard != clipboard_to_stay: + print("Deleting clipboard with id {}".format(clipboard.id)) + clipboard.delete() + + +def show_rollback_info_message(apps, schema_editor): + print("Clipboards do not need to be changed.") + + +class Migration(migrations.Migration): + + dependencies = [ + ('filer', '0002_auto_20150928_1109'), + ] + + operations = [ + migrations.RunPython(delete_extra_clipboards, + show_rollback_info_message) + ] diff --git a/filer/migrations/0004_auto__del_field_file__file__add_field_file_file__add_field_file_is_pub.py b/filer/migrations/0004_auto__del_field_file__file__add_field_file_file__add_field_file_is_pub.py deleted file mode 100644 index d36d8b650..000000000 --- a/filer/migrations/0004_auto__del_field_file__file__add_field_file_file__add_field_file_is_pub.py +++ /dev/null @@ -1,148 +0,0 @@ -# encoding: utf-8 -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - -class Migration(SchemaMigration): - - def forwards(self, orm): - - # Rename field 'file._file' - db.rename_column('filer_file', '_file', 'file') - - # Adding field 'File.is_public' - db.add_column('filer_file', 'is_public', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) - - - # no need to do this. south just *thinks* something has changed, because it did not know anything about through in earlier versions - # Removing M2M table for field files on 'clipboard' - #db.delete_table('filer_clipboard_files') - - - def backwards(self, orm): - - # Rename field 'file._file' - db.rename_column('filer_file', 'file', '_file') - - # Deleting field 'File.is_public' - db.delete_column('filer_file', 'is_public') - - # no need to do this. south just *thinks* something has changed, because it did not know anything about through in earlier versions - - # Adding M2M table for field files on 'clipboard' -# db.create_table('filer_clipboard_files', ( -# ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), -# ('clipboard', models.ForeignKey(orm['filer.clipboard'], null=False)), -# ('file', models.ForeignKey(orm['filer.file'], null=False)) -# )) -# db.create_unique('filer_clipboard_files', ['clipboard_id', 'file_id']) - - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'filer.clipboard': { - 'Meta': {'object_name': 'Clipboard'}, - 'files': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'in_clipboards'", 'symmetrical': 'False', 'through': "orm['filer.ClipboardItem']", 'to': "orm['filer.File']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'filer_clipboards'", 'to': "orm['auth.User']"}) - }, - 'filer.clipboarditem': { - 'Meta': {'object_name': 'ClipboardItem'}, - 'clipboard': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.Clipboard']"}), - 'file': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.File']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) - }, - 'filer.file': { - 'Meta': {'object_name': 'File'}, - '_file_size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - '_file_type_plugin_name': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'file': ('django.db.models.fields.files.FileField', [], {}), - 'folder': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'all_files'", 'null': 'True', 'to': "orm['filer.Folder']"}), - 'has_all_mandatory_data': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'original_filename': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'owned_files'", 'null': 'True', 'to': "orm['auth.User']"}), - 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) - }, - 'filer.folder': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('parent', 'name'),)", 'object_name': 'Folder'}, - 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_owned_folders'", 'null': 'True', 'to': "orm['auth.User']"}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['filer.Folder']"}), - 'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) - }, - 'filer.folderpermission': { - 'Meta': {'object_name': 'FolderPermission'}, - 'can_add_children': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'can_edit': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'can_read': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'everybody': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'folder': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.Folder']", 'null': 'True', 'blank': 'True'}), - 'group': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_folder_permissions'", 'null': 'True', 'to': "orm['auth.Group']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'type': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_folder_permissions'", 'null': 'True', 'to': "orm['auth.User']"}) - }, - 'filer.image': { - 'Meta': {'object_name': 'Image', '_ormbases': ['filer.File']}, - '_height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - '_width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'author': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'date_taken': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'default_alt_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'default_caption': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'file_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['filer.File']", 'unique': 'True', 'primary_key': 'True'}), - 'must_always_publish_author_credit': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'must_always_publish_copyright': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'subject_location': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '64', 'null': 'True', 'blank': 'True'}) - } - } - - complete_apps = ['filer'] diff --git a/filer/migrations/0004_unique_clipboard_per_user.py b/filer/migrations/0004_unique_clipboard_per_user.py new file mode 100644 index 000000000..c9b443af3 --- /dev/null +++ b/filer/migrations/0004_unique_clipboard_per_user.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- + + +from django.db import models, migrations +from django.conf import settings + + +class Migration(migrations.Migration): + + dependencies = [ + ('filer', '0003_delete_duplicate_clipboards'), + ] + + operations = [ + migrations.AlterField( + model_name='clipboard', + name='user', + field=models.OneToOneField(related_name='filer_clipboard', verbose_name='user', to=settings.AUTH_USER_MODEL, + on_delete=models.CASCADE), + ), + ] diff --git a/filer/migrations/0005_auto__add_field_file_sha1__chg_field_file_file.py b/filer/migrations/0005_auto__add_field_file_sha1__chg_field_file_file.py deleted file mode 100644 index 83c5ef92c..000000000 --- a/filer/migrations/0005_auto__add_field_file_sha1__chg_field_file_file.py +++ /dev/null @@ -1,134 +0,0 @@ -# encoding: utf-8 -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - -class Migration(SchemaMigration): - - def forwards(self, orm): - - # Adding field 'File.sha1' - db.add_column('filer_file', 'sha1', self.gf('django.db.models.fields.CharField')(default='', max_length=40, blank=True), keep_default=False) - - # Changing field 'File.file' - db.alter_column('filer_file', 'file', self.gf('django.db.models.fields.files.FileField')(max_length=255, null=True)) - - - def backwards(self, orm): - - # Deleting field 'File.sha1' - db.delete_column('filer_file', 'sha1') - - # Changing field 'File.file' - db.alter_column('filer_file', 'file', self.gf('django.db.models.fields.files.FileField')()) - - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'filer.clipboard': { - 'Meta': {'object_name': 'Clipboard'}, - 'files': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'in_clipboards'", 'symmetrical': 'False', 'through': "orm['filer.ClipboardItem']", 'to': "orm['filer.File']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'filer_clipboards'", 'to': "orm['auth.User']"}) - }, - 'filer.clipboarditem': { - 'Meta': {'object_name': 'ClipboardItem'}, - 'clipboard': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.Clipboard']"}), - 'file': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.File']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) - }, - 'filer.file': { - 'Meta': {'object_name': 'File'}, - '_file_size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - '_file_type_plugin_name': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'folder': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'all_files'", 'null': 'True', 'to': "orm['filer.Folder']"}), - 'has_all_mandatory_data': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'original_filename': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'owned_files'", 'null': 'True', 'to': "orm['auth.User']"}), - 'sha1': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '40', 'blank': 'True'}), - 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) - }, - 'filer.folder': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('parent', 'name'),)", 'object_name': 'Folder'}, - 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_owned_folders'", 'null': 'True', 'to': "orm['auth.User']"}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['filer.Folder']"}), - 'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) - }, - 'filer.folderpermission': { - 'Meta': {'object_name': 'FolderPermission'}, - 'can_add_children': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'can_edit': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'can_read': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'everybody': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'folder': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.Folder']", 'null': 'True', 'blank': 'True'}), - 'group': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_folder_permissions'", 'null': 'True', 'to': "orm['auth.Group']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'type': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_folder_permissions'", 'null': 'True', 'to': "orm['auth.User']"}) - }, - 'filer.image': { - 'Meta': {'object_name': 'Image', '_ormbases': ['filer.File']}, - '_height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - '_width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'author': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'date_taken': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'default_alt_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'default_caption': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'file_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['filer.File']", 'unique': 'True', 'primary_key': 'True'}), - 'must_always_publish_author_credit': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'must_always_publish_copyright': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'subject_location': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '64', 'null': 'True', 'blank': 'True'}) - } - } - - complete_apps = ['filer'] diff --git a/filer/migrations/0005_default_alt_text_size.py b/filer/migrations/0005_default_alt_text_size.py new file mode 100644 index 000000000..f5c127e5f --- /dev/null +++ b/filer/migrations/0005_default_alt_text_size.py @@ -0,0 +1,15 @@ +from django.db import migrations, models + +class Migration(migrations.Migration): + + dependencies = [ + ('filer', '0004_unique_clipboard_per_user'), + ] + + operations = [ + migrations.AlterField( + model_name='Image', + name='default_alt_text', + field=models.TextField(null=True), # Use TextField to allow unlimited length + ), + ] \ No newline at end of file diff --git a/filer/migrations/0006_default_caption_text_size.py b/filer/migrations/0006_default_caption_text_size.py new file mode 100644 index 000000000..32f60395c --- /dev/null +++ b/filer/migrations/0006_default_caption_text_size.py @@ -0,0 +1,15 @@ +from django.db import migrations, models + +class Migration(migrations.Migration): + + dependencies = [ + ('filer', '0005_default_alt_text_size'), + ] + + operations = [ + migrations.AlterField( + model_name='Image', + name='default_caption', + field=models.TextField(null=True), # Use TextField to allow unlimited length + ), + ] \ No newline at end of file diff --git a/filer/migrations/0006_polymorphic__add_field_file_polymorphic_ctype.py b/filer/migrations/0006_polymorphic__add_field_file_polymorphic_ctype.py deleted file mode 100644 index 65fd28576..000000000 --- a/filer/migrations/0006_polymorphic__add_field_file_polymorphic_ctype.py +++ /dev/null @@ -1,129 +0,0 @@ -# encoding: utf-8 -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - -class Migration(SchemaMigration): - - def forwards(self, orm): - - # Adding field 'File.polymorphic_ctype' - db.add_column('filer_file', 'polymorphic_ctype', self.gf('django.db.models.fields.related.ForeignKey')(related_name='polymorphic_filer.file_set', null=True, to=orm['contenttypes.ContentType']), keep_default=False) - - - def backwards(self, orm): - - # Deleting field 'File.polymorphic_ctype' - db.delete_column('filer_file', 'polymorphic_ctype_id') - - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'filer.clipboard': { - 'Meta': {'object_name': 'Clipboard'}, - 'files': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'in_clipboards'", 'symmetrical': 'False', 'through': "orm['filer.ClipboardItem']", 'to': "orm['filer.File']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'filer_clipboards'", 'to': "orm['auth.User']"}) - }, - 'filer.clipboarditem': { - 'Meta': {'object_name': 'ClipboardItem'}, - 'clipboard': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.Clipboard']"}), - 'file': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.File']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) - }, - 'filer.file': { - 'Meta': {'object_name': 'File'}, - '_file_size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - '_file_type_plugin_name': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'folder': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'all_files'", 'null': 'True', 'to': "orm['filer.Folder']"}), - 'has_all_mandatory_data': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'original_filename': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'owned_files'", 'null': 'True', 'to': "orm['auth.User']"}), - 'polymorphic_ctype': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'polymorphic_filer.file_set'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}), - 'sha1': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '40', 'blank': 'True'}), - 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) - }, - 'filer.folder': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('parent', 'name'),)", 'object_name': 'Folder'}, - 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_owned_folders'", 'null': 'True', 'to': "orm['auth.User']"}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['filer.Folder']"}), - 'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) - }, - 'filer.folderpermission': { - 'Meta': {'object_name': 'FolderPermission'}, - 'can_add_children': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'can_edit': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'can_read': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'everybody': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'folder': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.Folder']", 'null': 'True', 'blank': 'True'}), - 'group': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_folder_permissions'", 'null': 'True', 'to': "orm['auth.Group']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'type': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_folder_permissions'", 'null': 'True', 'to': "orm['auth.User']"}) - }, - 'filer.image': { - 'Meta': {'object_name': 'Image', '_ormbases': ['filer.File']}, - '_height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - '_width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'author': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'date_taken': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'default_alt_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'default_caption': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'file_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['filer.File']", 'unique': 'True', 'primary_key': 'True'}), - 'must_always_publish_author_credit': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'must_always_publish_copyright': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'subject_location': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '64', 'null': 'True', 'blank': 'True'}) - } - } - - complete_apps = ['filer'] diff --git a/filer/migrations/0007_filer_file_size.py b/filer/migrations/0007_filer_file_size.py new file mode 100644 index 000000000..ff820b6d9 --- /dev/null +++ b/filer/migrations/0007_filer_file_size.py @@ -0,0 +1,15 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ('filer', '0006_default_caption_text_size'), + ] + + operations = [ + migrations.AlterField( + model_name='File', + name='file', + field=models.CharField(null=True, blank=True, db_index=True, max_length=1024), + ), + ] diff --git a/filer/migrations/0007_polymorphic__content_type_data.py b/filer/migrations/0007_polymorphic__content_type_data.py deleted file mode 100644 index a8fdadf59..000000000 --- a/filer/migrations/0007_polymorphic__content_type_data.py +++ /dev/null @@ -1,144 +0,0 @@ -# encoding: utf-8 -import datetime -from django.core.exceptions import ObjectDoesNotExist -from south.db import db -from south.v2 import DataMigration -from django.db import models - -class Migration(DataMigration): - - def forwards(self, orm): - "Write your forwards methods here." - try: - image_ct = orm['contenttypes.ContentType'].objects.get(app_label='filer', model='image').id - file_ct = orm['contenttypes.ContentType'].objects.get(app_label='filer', model='file').id - for file in orm['filer.file'].objects.all(): - if file._file_type_plugin_name == 'Image': - file.polymorphic_ctype_id = image_ct - else: - file.polymorphic_ctype_id = file_ct - file.save() - except ObjectDoesNotExist: - print "No filer contentypes to migrate. This is probably because migrate is running on a new database." - - - def backwards(self, orm): - "Write your backwards methods here." - image_ct = orm['contenttypes.ContentType'].objects.get(app_label='filer', model='image').id - for file in orm['filer.file'].objects.all(): - if file.polymorphic_ctype_id == image_ct: - file._file_type_plugin_name = "Image" - else: - file._file_type_plugin_name = None - file.save() - - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'filer.clipboard': { - 'Meta': {'object_name': 'Clipboard'}, - 'files': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'in_clipboards'", 'symmetrical': 'False', 'through': "orm['filer.ClipboardItem']", 'to': "orm['filer.File']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'filer_clipboards'", 'to': "orm['auth.User']"}) - }, - 'filer.clipboarditem': { - 'Meta': {'object_name': 'ClipboardItem'}, - 'clipboard': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.Clipboard']"}), - 'file': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.File']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) - }, - 'filer.file': { - 'Meta': {'object_name': 'File'}, - '_file_size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - '_file_type_plugin_name': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'folder': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'all_files'", 'null': 'True', 'to': "orm['filer.Folder']"}), - 'has_all_mandatory_data': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'original_filename': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'owned_files'", 'null': 'True', 'to': "orm['auth.User']"}), - 'polymorphic_ctype': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'polymorphic_filer.file_set'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}), - 'sha1': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '40', 'blank': 'True'}), - 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) - }, - 'filer.folder': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('parent', 'name'),)", 'object_name': 'Folder'}, - 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_owned_folders'", 'null': 'True', 'to': "orm['auth.User']"}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['filer.Folder']"}), - 'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) - }, - 'filer.folderpermission': { - 'Meta': {'object_name': 'FolderPermission'}, - 'can_add_children': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'can_edit': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'can_read': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'everybody': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'folder': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.Folder']", 'null': 'True', 'blank': 'True'}), - 'group': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_folder_permissions'", 'null': 'True', 'to': "orm['auth.Group']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'type': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_folder_permissions'", 'null': 'True', 'to': "orm['auth.User']"}) - }, - 'filer.image': { - 'Meta': {'object_name': 'Image', '_ormbases': ['filer.File']}, - '_height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - '_width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'author': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'date_taken': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'default_alt_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'default_caption': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'file_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['filer.File']", 'unique': 'True', 'primary_key': 'True'}), - 'must_always_publish_author_credit': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'must_always_publish_copyright': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'subject_location': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '64', 'null': 'True', 'blank': 'True'}) - } - } - - complete_apps = ['filer'] diff --git a/filer/migrations/0008_polymorphic__del_field_file__file_type_plugin_name.py b/filer/migrations/0008_polymorphic__del_field_file__file_type_plugin_name.py deleted file mode 100644 index c2a9b44f0..000000000 --- a/filer/migrations/0008_polymorphic__del_field_file__file_type_plugin_name.py +++ /dev/null @@ -1,128 +0,0 @@ -# encoding: utf-8 -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - -class Migration(SchemaMigration): - - def forwards(self, orm): - - # Deleting field 'File._file_type_plugin_name' - db.delete_column('filer_file', '_file_type_plugin_name') - - - def backwards(self, orm): - - # Adding field 'File._file_type_plugin_name' - db.add_column('filer_file', '_file_type_plugin_name', self.gf('django.db.models.fields.CharField')(max_length=128, null=True, blank=True), keep_default=False) - - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'filer.clipboard': { - 'Meta': {'object_name': 'Clipboard'}, - 'files': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'in_clipboards'", 'symmetrical': 'False', 'through': "orm['filer.ClipboardItem']", 'to': "orm['filer.File']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'filer_clipboards'", 'to': "orm['auth.User']"}) - }, - 'filer.clipboarditem': { - 'Meta': {'object_name': 'ClipboardItem'}, - 'clipboard': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.Clipboard']"}), - 'file': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.File']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) - }, - 'filer.file': { - 'Meta': {'object_name': 'File'}, - '_file_size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'folder': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'all_files'", 'null': 'True', 'to': "orm['filer.Folder']"}), - 'has_all_mandatory_data': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'original_filename': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'owned_files'", 'null': 'True', 'to': "orm['auth.User']"}), - 'polymorphic_ctype': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'polymorphic_filer.file_set'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}), - 'sha1': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '40', 'blank': 'True'}), - 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) - }, - 'filer.folder': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('parent', 'name'),)", 'object_name': 'Folder'}, - 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_owned_folders'", 'null': 'True', 'to': "orm['auth.User']"}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['filer.Folder']"}), - 'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) - }, - 'filer.folderpermission': { - 'Meta': {'object_name': 'FolderPermission'}, - 'can_add_children': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'can_edit': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'can_read': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'everybody': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'folder': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.Folder']", 'null': 'True', 'blank': 'True'}), - 'group': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_folder_permissions'", 'null': 'True', 'to': "orm['auth.Group']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'type': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_folder_permissions'", 'null': 'True', 'to': "orm['auth.User']"}) - }, - 'filer.image': { - 'Meta': {'object_name': 'Image', '_ormbases': ['filer.File']}, - '_height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - '_width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'author': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'date_taken': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'default_alt_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'default_caption': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'file_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['filer.File']", 'unique': 'True', 'primary_key': 'True'}), - 'must_always_publish_author_credit': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'must_always_publish_copyright': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'subject_location': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '64', 'null': 'True', 'blank': 'True'}) - } - } - - complete_apps = ['filer'] diff --git a/filer/migrations/0008_thumbnailoption_alter_image_options_and_more.py b/filer/migrations/0008_thumbnailoption_alter_image_options_and_more.py new file mode 100644 index 000000000..97260eb30 --- /dev/null +++ b/filer/migrations/0008_thumbnailoption_alter_image_options_and_more.py @@ -0,0 +1,133 @@ +# Generated by Django 5.1.15 on 2026-04-30 04:52 + +import django.db.models.deletion +import filer.fields.multistorage_file +import filer.models.filemodels +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ('contenttypes', '0002_remove_content_type_name'), + ('filer', '0007_filer_file_size'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='ThumbnailOption', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100, verbose_name='name')), + ('width', models.IntegerField(help_text='width in pixel.', verbose_name='width')), + ('height', models.IntegerField(help_text='height in pixel.', verbose_name='height')), + ('crop', models.BooleanField(default=True, verbose_name='crop')), + ('upscale', models.BooleanField(default=True, verbose_name='upscale')), + ], + options={ + 'verbose_name': 'thumbnail option', + 'verbose_name_plural': 'thumbnail options', + 'ordering': ('width', 'height'), + }, + ), + migrations.AlterModelOptions( + name='image', + options={'default_manager_name': 'objects', 'verbose_name': 'image', 'verbose_name_plural': 'images'}, + ), + migrations.AddField( + model_name='file', + name='mime_type', + field=models.CharField(default='application/octet-stream', help_text='MIME type of uploaded content', max_length=255, validators=[filer.models.filemodels.mimetype_validator]), + ), + migrations.AddField( + model_name='image', + name='_transparent', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='file', + name='_file_size', + field=models.BigIntegerField(blank=True, null=True, verbose_name='file size'), + ), + migrations.AlterField( + model_name='file', + name='file', + field=filer.fields.multistorage_file.MultiStorageFileField(blank=True, db_index=True, max_length=1024, null=True, upload_to=filer.fields.multistorage_file.generate_filename_multistorage, verbose_name='file'), + ), + migrations.AlterField( + model_name='file', + name='owner', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='owned_%(class)ss', to=settings.AUTH_USER_MODEL, verbose_name='owner'), + ), + migrations.AlterField( + model_name='file', + name='polymorphic_ctype', + field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype'), + ), + migrations.AlterField( + model_name='folder', + name='level', + field=models.PositiveIntegerField(editable=False), + ), + migrations.AlterField( + model_name='folder', + name='lft', + field=models.PositiveIntegerField(editable=False), + ), + migrations.AlterField( + model_name='folder', + name='rght', + field=models.PositiveIntegerField(editable=False), + ), + migrations.AlterField( + model_name='image', + name='_height', + field=models.FloatField(blank=True, null=True), + ), + migrations.AlterField( + model_name='image', + name='_width', + field=models.FloatField(blank=True, null=True), + ), + migrations.AlterField( + model_name='image', + name='default_alt_text', + field=models.CharField(blank=True, max_length=255, null=True, verbose_name='default alt text'), + ), + migrations.AlterField( + model_name='image', + name='default_caption', + field=models.CharField(blank=True, max_length=255, null=True, verbose_name='default caption'), + ), + migrations.AlterField( + model_name='image', + name='file_ptr', + field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='%(app_label)s_%(class)s_file', serialize=False, to='filer.file'), + ), + migrations.AlterField( + model_name='image', + name='subject_location', + field=models.CharField(blank=True, default='', max_length=64, verbose_name='subject location'), + ), + migrations.CreateModel( + name='FolderPermission', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('type', models.SmallIntegerField(choices=[(0, 'all items'), (1, 'this item only'), (2, 'this item and all children')], default=0, verbose_name='type')), + ('everybody', models.BooleanField(default=False, verbose_name='everybody')), + ('can_read', models.SmallIntegerField(blank=True, choices=[(None, 'inherit'), (1, 'allow'), (0, 'deny')], default=None, null=True, verbose_name='can read')), + ('can_edit', models.SmallIntegerField(blank=True, choices=[(None, 'inherit'), (1, 'allow'), (0, 'deny')], default=None, null=True, verbose_name='can edit')), + ('can_add_children', models.SmallIntegerField(blank=True, choices=[(None, 'inherit'), (1, 'allow'), (0, 'deny')], default=None, null=True, verbose_name='can add children')), + ('folder', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='filer.folder', verbose_name='folder')), + ('group', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='filer_folder_permissions', to='auth.group', verbose_name='group')), + ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='filer_folder_permissions', to=settings.AUTH_USER_MODEL, verbose_name='user')), + ], + options={ + 'verbose_name': 'folder permission', + 'verbose_name_plural': 'folder permissions', + }, + ), + ] diff --git a/filer/migrations/0009_auto__add_field_folderpermission_can_edit_new__add_field_folderpermiss.py b/filer/migrations/0009_auto__add_field_folderpermission_can_edit_new__add_field_folderpermiss.py deleted file mode 100644 index 63e892e25..000000000 --- a/filer/migrations/0009_auto__add_field_folderpermission_can_edit_new__add_field_folderpermiss.py +++ /dev/null @@ -1,148 +0,0 @@ -# -*- coding: utf-8 -*- -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - - -class Migration(SchemaMigration): - - def forwards(self, orm): - # Adding field 'FolderPermission.can_edit_new' - db.add_column('filer_folderpermission', 'can_edit_new', - self.gf('django.db.models.fields.SmallIntegerField')(default=None, null=True, blank=True), - keep_default=False) - - # Adding field 'FolderPermission.can_read_new' - db.add_column('filer_folderpermission', 'can_read_new', - self.gf('django.db.models.fields.SmallIntegerField')(default=None, null=True, blank=True), - keep_default=False) - - # Adding field 'FolderPermission.can_add_children_new' - db.add_column('filer_folderpermission', 'can_add_children_new', - self.gf('django.db.models.fields.SmallIntegerField')(default=None, null=True, blank=True), - keep_default=False) - - - def backwards(self, orm): - # Deleting field 'FolderPermission.can_edit_new' - db.delete_column('filer_folderpermission', 'can_edit_new') - - # Deleting field 'FolderPermission.can_read_new' - db.delete_column('filer_folderpermission', 'can_read_new') - - # Deleting field 'FolderPermission.can_add_children_new' - db.delete_column('filer_folderpermission', 'can_add_children_new') - - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'filer.clipboard': { - 'Meta': {'object_name': 'Clipboard'}, - 'files': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'in_clipboards'", 'symmetrical': 'False', 'through': "orm['filer.ClipboardItem']", 'to': "orm['filer.File']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'filer_clipboards'", 'to': "orm['auth.User']"}) - }, - 'filer.clipboarditem': { - 'Meta': {'object_name': 'ClipboardItem'}, - 'clipboard': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.Clipboard']"}), - 'file': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.File']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) - }, - 'filer.file': { - 'Meta': {'object_name': 'File'}, - '_file_size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'folder': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'all_files'", 'null': 'True', 'to': "orm['filer.Folder']"}), - 'has_all_mandatory_data': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'original_filename': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'owned_files'", 'null': 'True', 'to': "orm['auth.User']"}), - 'polymorphic_ctype': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'polymorphic_filer.file_set'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}), - 'sha1': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '40', 'blank': 'True'}), - 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) - }, - 'filer.folder': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('parent', 'name'),)", 'object_name': 'Folder'}, - 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_owned_folders'", 'null': 'True', 'to': "orm['auth.User']"}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['filer.Folder']"}), - 'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) - }, - 'filer.folderpermission': { - 'Meta': {'object_name': 'FolderPermission'}, - 'can_add_children': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'can_add_children_new': ('django.db.models.fields.SmallIntegerField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), - 'can_edit': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'can_edit_new': ('django.db.models.fields.SmallIntegerField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), - 'can_read': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'can_read_new': ('django.db.models.fields.SmallIntegerField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), - 'everybody': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'folder': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.Folder']", 'null': 'True', 'blank': 'True'}), - 'group': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_folder_permissions'", 'null': 'True', 'to': "orm['auth.Group']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'type': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_folder_permissions'", 'null': 'True', 'to': "orm['auth.User']"}) - }, - 'filer.image': { - 'Meta': {'object_name': 'Image', '_ormbases': ['filer.File']}, - '_height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - '_width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'author': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'date_taken': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'default_alt_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'default_caption': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'file_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['filer.File']", 'unique': 'True', 'primary_key': 'True'}), - 'must_always_publish_author_credit': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'must_always_publish_copyright': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'subject_location': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '64', 'null': 'True', 'blank': 'True'}) - } - } - - complete_apps = ['filer'] \ No newline at end of file diff --git a/filer/migrations/0010_folderpermissions.py b/filer/migrations/0010_folderpermissions.py deleted file mode 100644 index 674b7bb2f..000000000 --- a/filer/migrations/0010_folderpermissions.py +++ /dev/null @@ -1,137 +0,0 @@ -# -*- coding: utf-8 -*- -import datetime -from south.db import db -from south.v2 import DataMigration -from django.db import models - -class Migration(DataMigration): - ALLOW = 1 - DENY = 0 - - def forwards(self, orm): - for permission in orm.FolderPermission.objects.all(): - permission.can_edit_new = self.ALLOW if permission.can_edit else self.DENY - permission.can_read_new = self.ALLOW if permission.can_read else self.DENY - permission.can_add_children_new = self.ALLOW if permission.can_add_children else self.DENY - permission.save() - - def backwards(self, orm): - # Backwards migration is lossy, but we play on a safe side and deny more - for permission in orm.FolderPermission.objects.all(): - permission.can_edit = permission.can_edit_new == self.ALLOW - permission.can_read = permission.can_read_new == self.ALLOW - permission.can_add_children = permission.can_add_children_new == self.ALLOW - permission.save() - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'filer.clipboard': { - 'Meta': {'object_name': 'Clipboard'}, - 'files': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'in_clipboards'", 'symmetrical': 'False', 'through': "orm['filer.ClipboardItem']", 'to': "orm['filer.File']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'filer_clipboards'", 'to': "orm['auth.User']"}) - }, - 'filer.clipboarditem': { - 'Meta': {'object_name': 'ClipboardItem'}, - 'clipboard': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.Clipboard']"}), - 'file': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.File']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) - }, - 'filer.file': { - 'Meta': {'object_name': 'File'}, - '_file_size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'folder': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'all_files'", 'null': 'True', 'to': "orm['filer.Folder']"}), - 'has_all_mandatory_data': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'original_filename': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'owned_files'", 'null': 'True', 'to': "orm['auth.User']"}), - 'polymorphic_ctype': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'polymorphic_filer.file_set'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}), - 'sha1': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '40', 'blank': 'True'}), - 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) - }, - 'filer.folder': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('parent', 'name'),)", 'object_name': 'Folder'}, - 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_owned_folders'", 'null': 'True', 'to': "orm['auth.User']"}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['filer.Folder']"}), - 'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) - }, - 'filer.folderpermission': { - 'Meta': {'object_name': 'FolderPermission'}, - 'can_add_children': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'can_add_children_new': ('django.db.models.fields.SmallIntegerField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), - 'can_edit': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'can_edit_new': ('django.db.models.fields.SmallIntegerField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), - 'can_read': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'can_read_new': ('django.db.models.fields.SmallIntegerField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), - 'everybody': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'folder': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.Folder']", 'null': 'True', 'blank': 'True'}), - 'group': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_folder_permissions'", 'null': 'True', 'to': "orm['auth.Group']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'type': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_folder_permissions'", 'null': 'True', 'to': "orm['auth.User']"}) - }, - 'filer.image': { - 'Meta': {'object_name': 'Image', '_ormbases': ['filer.File']}, - '_height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - '_width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'author': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'date_taken': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'default_alt_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'default_caption': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'file_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['filer.File']", 'unique': 'True', 'primary_key': 'True'}), - 'must_always_publish_author_credit': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'must_always_publish_copyright': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'subject_location': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '64', 'null': 'True', 'blank': 'True'}) - } - } - - complete_apps = ['filer'] - symmetrical = True diff --git a/filer/migrations/0011_auto__del_field_folderpermission_can_add_children__del_field_folderper.py b/filer/migrations/0011_auto__del_field_folderpermission_can_add_children__del_field_folderper.py deleted file mode 100644 index cd165ad59..000000000 --- a/filer/migrations/0011_auto__del_field_folderpermission_can_add_children__del_field_folderper.py +++ /dev/null @@ -1,145 +0,0 @@ -# -*- coding: utf-8 -*- -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - - -class Migration(SchemaMigration): - - def forwards(self, orm): - # Deleting field 'FolderPermission.can_add_children' - db.delete_column('filer_folderpermission', 'can_add_children') - - # Deleting field 'FolderPermission.can_edit' - db.delete_column('filer_folderpermission', 'can_edit') - - # Deleting field 'FolderPermission.can_read' - db.delete_column('filer_folderpermission', 'can_read') - - - def backwards(self, orm): - # Adding field 'FolderPermission.can_add_children' - db.add_column('filer_folderpermission', 'can_add_children', - self.gf('django.db.models.fields.BooleanField')(default=True), - keep_default=False) - - # Adding field 'FolderPermission.can_edit' - db.add_column('filer_folderpermission', 'can_edit', - self.gf('django.db.models.fields.BooleanField')(default=True), - keep_default=False) - - # Adding field 'FolderPermission.can_read' - db.add_column('filer_folderpermission', 'can_read', - self.gf('django.db.models.fields.BooleanField')(default=True), - keep_default=False) - - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'filer.clipboard': { - 'Meta': {'object_name': 'Clipboard'}, - 'files': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'in_clipboards'", 'symmetrical': 'False', 'through': "orm['filer.ClipboardItem']", 'to': "orm['filer.File']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'filer_clipboards'", 'to': "orm['auth.User']"}) - }, - 'filer.clipboarditem': { - 'Meta': {'object_name': 'ClipboardItem'}, - 'clipboard': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.Clipboard']"}), - 'file': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.File']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) - }, - 'filer.file': { - 'Meta': {'object_name': 'File'}, - '_file_size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'folder': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'all_files'", 'null': 'True', 'to': "orm['filer.Folder']"}), - 'has_all_mandatory_data': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'original_filename': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'owned_files'", 'null': 'True', 'to': "orm['auth.User']"}), - 'polymorphic_ctype': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'polymorphic_filer.file_set'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}), - 'sha1': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '40', 'blank': 'True'}), - 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) - }, - 'filer.folder': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('parent', 'name'),)", 'object_name': 'Folder'}, - 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_owned_folders'", 'null': 'True', 'to': "orm['auth.User']"}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['filer.Folder']"}), - 'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) - }, - 'filer.folderpermission': { - 'Meta': {'object_name': 'FolderPermission'}, - 'can_add_children_new': ('django.db.models.fields.SmallIntegerField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), - 'can_edit_new': ('django.db.models.fields.SmallIntegerField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), - 'can_read_new': ('django.db.models.fields.SmallIntegerField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), - 'everybody': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'folder': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.Folder']", 'null': 'True', 'blank': 'True'}), - 'group': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_folder_permissions'", 'null': 'True', 'to': "orm['auth.Group']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'type': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_folder_permissions'", 'null': 'True', 'to': "orm['auth.User']"}) - }, - 'filer.image': { - 'Meta': {'object_name': 'Image', '_ormbases': ['filer.File']}, - '_height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - '_width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'author': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'date_taken': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'default_alt_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'default_caption': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'file_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['filer.File']", 'unique': 'True', 'primary_key': 'True'}), - 'must_always_publish_author_credit': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'must_always_publish_copyright': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'subject_location': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '64', 'null': 'True', 'blank': 'True'}) - } - } - - complete_apps = ['filer'] \ No newline at end of file diff --git a/filer/migrations/0012_renaming_folderpermissions.py b/filer/migrations/0012_renaming_folderpermissions.py deleted file mode 100644 index d0522f05a..000000000 --- a/filer/migrations/0012_renaming_folderpermissions.py +++ /dev/null @@ -1,127 +0,0 @@ -# -*- coding: utf-8 -*- -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - - -class Migration(SchemaMigration): - - def forwards(self, orm): - db.rename_column('filer_folderpermission', 'can_edit_new', 'can_edit') - db.rename_column('filer_folderpermission', 'can_read_new', 'can_read') - db.rename_column('filer_folderpermission', 'can_add_children_new', 'can_add_children') - - def backwards(self, orm): - db.rename_column('filer_folderpermission', 'can_edit', 'can_edit_new') - db.rename_column('filer_folderpermission', 'can_read', 'can_read_new') - db.rename_column('filer_folderpermission', 'can_add_children', 'can_add_children_new') - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'filer.clipboard': { - 'Meta': {'object_name': 'Clipboard'}, - 'files': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'in_clipboards'", 'symmetrical': 'False', 'through': "orm['filer.ClipboardItem']", 'to': "orm['filer.File']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'filer_clipboards'", 'to': "orm['auth.User']"}) - }, - 'filer.clipboarditem': { - 'Meta': {'object_name': 'ClipboardItem'}, - 'clipboard': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.Clipboard']"}), - 'file': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.File']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) - }, - 'filer.file': { - 'Meta': {'object_name': 'File'}, - '_file_size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'folder': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'all_files'", 'null': 'True', 'to': "orm['filer.Folder']"}), - 'has_all_mandatory_data': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'original_filename': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'owned_files'", 'null': 'True', 'to': "orm['auth.User']"}), - 'polymorphic_ctype': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'polymorphic_filer.file_set'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}), - 'sha1': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '40', 'blank': 'True'}), - 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) - }, - 'filer.folder': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('parent', 'name'),)", 'object_name': 'Folder'}, - 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_owned_folders'", 'null': 'True', 'to': "orm['auth.User']"}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['filer.Folder']"}), - 'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}), - 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) - }, - 'filer.folderpermission': { - 'Meta': {'object_name': 'FolderPermission'}, - 'can_add_children': ('django.db.models.fields.SmallIntegerField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), - 'can_edit': ('django.db.models.fields.SmallIntegerField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), - 'can_read': ('django.db.models.fields.SmallIntegerField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), - 'everybody': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'folder': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.Folder']", 'null': 'True', 'blank': 'True'}), - 'group': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_folder_permissions'", 'null': 'True', 'to': "orm['auth.Group']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'type': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_folder_permissions'", 'null': 'True', 'to': "orm['auth.User']"}) - }, - 'filer.image': { - 'Meta': {'object_name': 'Image', '_ormbases': ['filer.File']}, - '_height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - '_width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'author': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'date_taken': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'default_alt_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'default_caption': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'file_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['filer.File']", 'unique': 'True', 'primary_key': 'True'}), - 'must_always_publish_author_credit': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'must_always_publish_copyright': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'subject_location': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '64', 'null': 'True', 'blank': 'True'}) - } - } - - complete_apps = ['filer'] diff --git a/filer/models/__init__.py b/filer/models/__init__.py index 66a6550d1..05e3867af 100644 --- a/filer/models/__init__.py +++ b/filer/models/__init__.py @@ -1,6 +1,12 @@ -#-*- coding: utf-8 -*- -from filer.models.clipboardmodels import * -from filer.models.filemodels import * -from filer.models.foldermodels import * -from filer.models.imagemodels import * -from filer.models.virtualitems import * +from .clipboardmodels import * # noqa +from .filemodels import * # noqa +from .foldermodels import * # noqa +from .imagemodels import * # noqa +from .thumbnailoptionmodels import * # noqa +from .virtualitems import * # noqa + +# PBS-specific: keep archive models for backward compatibility +try: + from .archivemodels import * # noqa +except ImportError: + pass diff --git a/filer/models/abstract.py b/filer/models/abstract.py new file mode 100644 index 000000000..f4747fd23 --- /dev/null +++ b/filer/models/abstract.py @@ -0,0 +1,306 @@ +import logging + +from django.conf import settings +from django.core.checks import Warning +from django.core.checks import register as register_check +from django.core.exceptions import ValidationError +from django.db import models +from django.utils.functional import cached_property +from django.utils.translation import gettext_lazy as _ + +import easy_thumbnails.utils +try: + from easy_thumbnails.VIL import Image as VILImage +except (ImportError, ModuleNotFoundError): + VILImage = None +from PIL.Image import MAX_IMAGE_PIXELS + +from .. import settings as filer_settings +from ..utils.compatibility import PILImage +from ..utils.filer_easy_thumbnails import FilerThumbnailer +from ..utils.pil_exif import get_exif_for_file +from .filemodels import File + + +logger = logging.getLogger(__name__) + + +# We can never exceed the max pixel value set by Pillow's PIL Image MAX_IMAGE_PIXELS +# as if we allow it, it will fail while thumbnailing (first in the admin thumbnails +# and then in the page itself. +# Refer this https://github.com/python-pillow/Pillow/blob/b723e9e62e4706a85f7e44cb42b3d838dae5e546/src/PIL/Image.py#L3148 +FILER_MAX_IMAGE_PIXELS = getattr(settings, "FILER_MAX_IMAGE_PIXELS", MAX_IMAGE_PIXELS) +if MAX_IMAGE_PIXELS is not None: + FILER_MAX_IMAGE_PIXELS = min(FILER_MAX_IMAGE_PIXELS, MAX_IMAGE_PIXELS) + + +@register_check() +def max_pixel_setting_check(app_configs, **kwargs): + if not FILER_MAX_IMAGE_PIXELS: + return [ + Warning( + "Both settings.FILER_MAX_IMAGE_PIXELS and PIL.Image.MAX_IMAGE_PIXELS are not set.", + hint="Set FILER_MAX_IMAGE_PIXELS to a positive integer value in your settings.py. " + "This setting is used to limit the maximum number of pixels an image can have " + "to protect your site from memory bombs.", + obj=settings, + ) + ] + return [] + + +class BaseImage(File): + SIDEBAR_IMAGE_WIDTH = 210 + DEFAULT_THUMBNAILS = { + 'admin_clipboard_icon': {'size': (32, 32), 'crop': True, + 'upscale': True}, + 'admin_sidebar_preview': {'size': (SIDEBAR_IMAGE_WIDTH, 0), 'upscale': True}, + 'admin_directory_listing_icon': {'size': (48, 48), + 'crop': True, 'upscale': True}, + 'admin_tiny_icon': {'size': (32, 32), 'crop': True, 'upscale': True}, + } + file_type = 'Image' + _icon = "image" + _filename_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.svg', '.webp'] + + _height = models.FloatField( + null=True, + blank=True, + ) + + _width = models.FloatField( + null=True, + blank=True, + ) + + _transparent = models.BooleanField( + null=False, + default=False, + ) + + default_alt_text = models.CharField( + _("default alt text"), + max_length=255, + blank=True, + null=True, + ) + + default_caption = models.CharField( + _("default caption"), + max_length=255, + blank=True, + null=True, + ) + + subject_location = models.CharField( + _("subject location"), + max_length=64, + blank=True, + default='', + ) + + file_ptr = models.OneToOneField( + to='filer.File', + parent_link=True, + related_name='%(app_label)s_%(class)s_file', + on_delete=models.CASCADE, + ) + + class Meta: + app_label = 'filer' + verbose_name = _("image") + verbose_name_plural = _("images") + abstract = True + default_manager_name = 'objects' + + @classmethod + def matches_file_type(cls, iname, ifile, mime_type): + # source: https://www.freeformatter.com/mime-types-list.html + from ..settings import IMAGE_MIME_TYPES + if not mime_type: + return False + maintype, subtype = mime_type.split('/') + return maintype == 'image' and subtype in IMAGE_MIME_TYPES + + def file_data_changed(self, post_init=False): + attrs_updated = super().file_data_changed(post_init=post_init) + if attrs_updated: + try: + try: + imgfile = self.file.file + except ValueError: + imgfile = self.file_ptr.file + imgfile.seek(0) + if self.mime_type == 'image/svg+xml': + self._width, self._height = VILImage.load(imgfile).size + self._transparent = True + else: + pil_image = PILImage.open(imgfile) + self._width, self._height = pil_image.size + self._transparent = easy_thumbnails.utils.is_transparent(pil_image) + imgfile.seek(0) + except Exception as e: + logger.warning( + "Could not read image dimensions for '%s' (mime=%s): %s: %s", + getattr(self, 'original_filename', '?'), + getattr(self, 'mime_type', '?'), + type(e).__name__, + e, + ) + if post_init is False: + # in case `imgfile` could not be found, unset dimensions + # but only if not initialized by loading a fixture file + self._width, self._height = None, None + self._transparent = False + return attrs_updated + + def clean(self): + # We check the Image size and calculate the pixel before + # the image gets attached to a folder and saved. We also + # send the error msg in the JSON and also post the message + # so that they know what is wrong with the image they uploaded + # Only check pixel size for new uploads (no pk yet) + if self.file and FILER_MAX_IMAGE_PIXELS and not self.pk: + if self._width is None or self._height is None: + # Image dimensions could not be determined – this can happen + # for valid images that Pillow cannot fully parse (e.g. unusual + # JPEG markers, CMYK colour space, progressive encoding, etc.). + # Do NOT reject the upload; just skip the pixel-limit check and + # log a warning so operators can investigate if needed. + logger.warning( + "Skipping pixel-limit check for '%s' (mime=%s): " + "image dimensions could not be determined.", + getattr(self, 'original_filename', '?'), + getattr(self, 'mime_type', '?'), + ) + super().clean() + return + + width, height = max(1, self.width), max(1, self.height) + pixels: int = width * height + aspect: float = width / height + res_x: int = int((FILER_MAX_IMAGE_PIXELS * aspect) ** 0.5) + res_y: int = int(res_x / aspect) + if pixels > 2 * FILER_MAX_IMAGE_PIXELS: + msg = _( + "Image format not recognized or image size exceeds limit of %(max_pixels)d million " + "pixels by a factor of two or more. Before uploading again, check file format or resize " + "image to %(width)d x %(height)d resolution or lower." + ) % dict(max_pixels=FILER_MAX_IMAGE_PIXELS // 1000000, width=res_x, height=res_y) + raise ValidationError(str(msg), code="image_size") + + if pixels > FILER_MAX_IMAGE_PIXELS: + msg = _( + "Image size (%(pixels)d million pixels) exceeds limit of %(max_pixels)d " + "million pixels. Before uploading again, resize image to %(width)d x %(height)d " + "resolution or lower." + ) % dict(pixels=pixels // 1000000, max_pixels=FILER_MAX_IMAGE_PIXELS // 1000000, + width=res_x, height=res_y) + raise ValidationError(str(msg), code="image_size") + super().clean() + + def save(self, *args, **kwargs): + self.has_all_mandatory_data = self._check_validity() + super().save(*args, **kwargs) + + def _check_validity(self): + if not self.name: + return False + return True + + def sidebar_image_ratio(self): + if self.width: + return float(self.width) / float(self.SIDEBAR_IMAGE_WIDTH) + else: + return 1.0 + + @cached_property + def exif(self): + try: + return get_exif_for_file(self.file) + except Exception: + return {} + + def has_edit_permission(self, request): + return self.has_generic_permission(request, 'edit') + + def has_read_permission(self, request): + return self.has_generic_permission(request, 'read') + + def has_add_children_permission(self, request): + return self.has_generic_permission(request, 'add_children') + + def has_generic_permission(self, request, permission_type): + """ + Return true if the current user has permission on this + image. Return the string 'ALL' if the user has all rights. + """ + user = request.user + if not user.is_authenticated: + return False + elif user.is_superuser: + return True + elif user == self.owner: + return True + elif self.folder: + return self.folder.has_generic_permission(request, permission_type) + else: + return False + + @property + def label(self): + if self.name in ['', None]: + return self.original_filename or 'unnamed file' + else: + return self.name + + @property + def width(self): + return self._width or 0.0 + + @property + def height(self): + return self._height or 0.0 + + def _generate_thumbnails(self, required_thumbnails): + from filer.utils.cdn import get_cdn_url + _thumbnails = {} + for name, opts in required_thumbnails.items(): + try: + opts.update({'subject_location': self.subject_location}) + thumb = self.file.get_thumbnail(opts) + _thumbnails[name] = get_cdn_url(self, thumb.url) + except Exception as e: + # catch exception and manage it. We can re-raise it for debugging + # purposes and/or just logging it, provided user configured + # proper logging configuration + if filer_settings.FILER_ENABLE_LOGGING: + logger.error('Error while generating thumbnail: %s', e) + if filer_settings.FILER_DEBUG: + raise + return _thumbnails + + @property + def icons(self): + required_thumbnails = { + size: { + 'size': (int(size), int(size)), + 'crop': True, + 'upscale': True, + 'subject_location': self.subject_location, + } + for size in filer_settings.FILER_ADMIN_ICON_SIZES} + return self._generate_thumbnails(required_thumbnails) + + @property + def thumbnails(self): + return self._generate_thumbnails(BaseImage.DEFAULT_THUMBNAILS) + + @property + def easy_thumbnails_thumbnailer(self): + tn = FilerThumbnailer( + file=self.file, name=self.file.name, + source_storage=self.file.source_storage, + thumbnail_storage=self.file.thumbnail_storage, + thumbnail_basedir=self.file.thumbnail_basedir) + return tn diff --git a/filer/models/archivemodels.py b/filer/models/archivemodels.py new file mode 100644 index 000000000..3bc657119 --- /dev/null +++ b/filer/models/archivemodels.py @@ -0,0 +1,210 @@ +""" +Archiving support for filer. +""" +from filer.models.filemodels import File +from filer.models.foldermodels import Folder +from filer.models.imagemodels import Image as FilerImage +from django.utils.translation import gettext_lazy as _ +from django.core.files.base import ContentFile +from django.db.models import Q +from filer.settings import FILER_IS_PUBLIC_DEFAULT +from filer.utils.files import matching_file_subtypes +import os.path +import zipfile + +try: + from PIL import Image as PILImage +except ImportError: + try: + import Image as PILImage + except ImportError: + raise ImportError("The Python Imaging Library was not found.") + + +class Archive(File): + """ + Django model for manipulating archive files. + With extract, it creates the file structure from within a archive file. + Current supported archive file types: zip. + """ + file_type = 'Archive' + _icon = 'archive' + _filename_extensions = ['.zip', ] + + def __init__(self, *args, **kwargs): + super(Archive, self).__init__(*args, **kwargs) + self.extract_errors = [] + + @classmethod + def matches_file_type(cls, iname, ifile, request): + """Checks if the file has an archive type extension.""" + extension = os.path.splitext(iname)[-1].lower() + return extension in Archive._filename_extensions + + def extract(self, bypass_owner=False): + """Extracts the archive files' contents.""" + self.bypass_owner = bypass_owner + self.file.open() + self.extract_errors = [] + try: + self._extract_zip(self.file) + finally: + self.file.close() + + def is_valid(self): + """Checks if the file is a proper archive.""" + try: + self.file.open() + return self._is_valid_zip(self.file) + except: + return False + finally: + self.file.close() + + def collisions(self): + """ + Verifies that the files or folders about to be written don't already + exist. + Returns any duplicated files/folders. + """ + in_both = [] + self.file.open() + try: + in_both = self._collisions_zip(self.file) + finally: + self.file.close() + return in_both + + def _is_valid_zip(self, filer_file): + """Validates zip files.""" + is_valid = zipfile.is_zipfile(filer_file) + return is_valid + + def _collisions_zip(self, filer_file): + """Checks collisions for zip files.""" + zippy = zipfile.ZipFile(filer_file) + cwd = self.logical_folder + if cwd.is_root: + cwd_path = os.sep + orphan_files = [x.pretty_logical_path + for x in File.objects.filter(folder=None)] + orphan_folders = [x.pretty_logical_path + for x in Folder.objects.filter(parent=None)] + filer_paths = orphan_files + orphan_folders + else: + cwd_path = cwd.pretty_logical_path + os.sep + filer_paths = cwd.pretty_path_entries() + + zip_paths = [cwd_path + to_unicode(x).rstrip(os.sep) + for x in zippy.namelist()] + file_set = set(filer_paths) + intersection = [x for x in zip_paths if x in file_set] + return intersection + + def _extract_zip(self, filer_file): + """ + Creates the file and folder hierarchy from the contents of the zip + file. It first creates the parent folder of the selected file if it + does not already exist, similair to mkdir -p. + """ + import posixpath + zippy = zipfile.ZipFile(filer_file) + entries = zippy.infolist() + for entry in entries: + full_path = to_unicode(entry.filename) + # Use posixpath since zip files always use '/' as separator + filename = posixpath.basename(full_path) + parent_dir = self._create_parent_folders(full_path) + if filename: + data = zippy.read(entry) + self._create_file(filename, parent_dir, data) + + def _create_parent_folders(self, full_path): + """Creates the folder parents for a given entry.""" + # Zip files always use '/' as path separator, regardless of OS + dir_parents_of_entry = full_path.replace('\\', '/').split('/')[:-1] + parent_dir = self.folder + for directory_name in dir_parents_of_entry: + if not directory_name: + continue + parent_dir = self._create_folder( + directory_name, parent_dir) + return parent_dir + + def _create_folder(self, name, parent): + """ + Helper wrapper of creating a file in a filer folder. + If there already is a folder with the given name, it returnes that. + """ + attrs = dict(name=name, parent=parent) + if getattr(self, 'bypass_owner', False) is False: + attrs['owner'] = self.owner + + existing = Folder.objects.filter(**attrs) + if existing: + return existing[0] + # make sure owner is set + if parent: + attrs['parent'] = Folder.objects.get(id=parent.id) + attrs['owner'] = self.owner + return Folder.objects.create(**attrs) + + def _is_valid_image(self, content_file): + try: + PILImage.open(content_file) + except (IOError, ): + self.extract_errors.append( + "%s is not a valid image." % content_file.name) + else: + return True + return False + + def _create_file(self, basename, folder, data): + """Helper wrapper of creating a filer file.""" + import mimetypes + file_data = ContentFile(data, name=basename) + mime_type = mimetypes.guess_type(basename)[0] + matched_file_types = matching_file_subtypes(basename, None, mime_type) + FileSubClass = matched_file_types[0] + if (FileSubClass is FilerImage and + not self._is_valid_image(file_data)): + return + + actual_name_query = (Q(original_filename=basename) & ( + Q(name__isnull=True) | Q(name__exact=''))) | Q(name=basename) + + search_query = Q(folder=folder) & actual_name_query + + if getattr(self, 'bypass_owner', False) is False: + search_query &= Q(owner=self.owner) + + file_manager = FileSubClass.objects + existing = file_manager.filter(search_query) + file_object = None + if existing: + file_object = existing[0] + file_object.name = None + file_object.original_filename = basename + file_object.file = file_data + file_object.save() + else: + file_object = file_manager.create( + original_filename=basename, + folder=folder, + owner=self.owner, + file=file_data, + is_public=FILER_IS_PUBLIC_DEFAULT, + ) + return file_object + + class Meta: + """Meta information for filer file model.""" + app_label = 'filer' + verbose_name = _('archive') + verbose_name_plural = _('archives') + + +def to_unicode(x): # expects str or unicode + if isinstance(x, str): + return x + return x.decode('utf8') diff --git a/filer/models/clipboardmodels.py b/filer/models/clipboardmodels.py index 5bdd735c0..cde011818 100644 --- a/filer/models/clipboardmodels.py +++ b/filer/models/clipboardmodels.py @@ -1,19 +1,36 @@ -#-*- coding: utf-8 -*- +from django.conf import settings from django.contrib.auth import models as auth_models from django.db import models -from django.utils.translation import ugettext_lazy as _ -from filer.models import filemodels +from django.utils.translation import gettext_lazy as _ + +from . import filemodels class Clipboard(models.Model): - user = models.ForeignKey(auth_models.User, verbose_name=_('user'), related_name="filer_clipboards") + user = models.OneToOneField( + getattr(settings, 'AUTH_USER_MODEL', 'auth.User'), + verbose_name=_('user'), + related_name="filer_clipboard", + on_delete=models.CASCADE, + ) + files = models.ManyToManyField( - 'File', verbose_name=_('files'), related_name="in_clipboards", - through='ClipboardItem') + 'File', + verbose_name=_('files'), + related_name="in_clipboards", + through='ClipboardItem', + ) + + # PBS-specific: folder_name used for clipboard upload paths + folder_name = "_clipboard" + + class Meta: + app_label = 'filer' + verbose_name = _("clipboard") + verbose_name_plural = _("clipboards") def append_file(self, file_obj): try: - # We have to check if file is already in the clipboard as otherwise polymorphic complains self.files.get(pk=file_obj.pk) return False except filemodels.File.DoesNotExist: @@ -26,20 +43,24 @@ def empty(self): item.delete() empty.alters_data = True - def __unicode__(self): - return u"Clipboard %s of %s" % (self.id, self.user) - - class Meta: - app_label = 'filer' - verbose_name = _('clipboard') - verbose_name_plural = _('clipboards') + def __str__(self): + return f"Clipboard {self.id} of {self.user}" class ClipboardItem(models.Model): - file = models.ForeignKey('File', verbose_name=_('file')) - clipboard = models.ForeignKey(Clipboard, verbose_name=_('clipboard')) + file = models.ForeignKey( + 'File', + verbose_name=_("file"), + on_delete=models.CASCADE, + ) + + clipboard = models.ForeignKey( + Clipboard, + verbose_name=_("clipboard"), + on_delete=models.CASCADE, + ) class Meta: app_label = 'filer' - verbose_name = _('clipboard item') - verbose_name_plural = _('clipboard items') + verbose_name = _("clipboard item") + verbose_name_plural = _("clipboard items") diff --git a/filer/models/filemodels.py b/filer/models/filemodels.py index 8fd6471b6..2191aff6a 100644 --- a/filer/models/filemodels.py +++ b/filer/models/filemodels.py @@ -1,73 +1,366 @@ -#-*- coding: utf-8 -*- -from django.contrib.auth import models as auth_models -from django.core import urlresolvers -from django.core.files.base import ContentFile -from django.db import models -from django.utils.translation import ugettext_lazy as _ -from filer.fields.multistorage_file import MultiStorageFileField -from filer.models import mixins -from filer import settings as filer_settings -from filer.models.foldermodels import Folder -from polymorphic import PolymorphicModel, PolymorphicManager import hashlib +import mimetypes import os +import logging +from datetime import datetime, timezone + +from django.conf import settings +from django.contrib.auth import models as auth_models +from django.core.exceptions import ValidationError +from django.core.files.base import ContentFile +from django.db import models, IntegrityError, transaction +from django.db.models import DEFERRED, Count +from django.urls import NoReverseMatch, reverse +from django.utils.functional import cached_property +from django.utils import timezone as django_timezone +from django.utils.translation import gettext_lazy as _ + +from polymorphic.managers import PolymorphicManager +from polymorphic.models import PolymorphicModel +from polymorphic.query import PolymorphicQuerySet + +from .. import settings as filer_settings +from ..fields.multistorage_file import MultiStorageFileField +from ..utils.cache import invalidate_folder_listing_cache, invalidate_folder_listing_cache_for_file +from ..utils.cms_roles import ( + get_sites_without_restriction_perm, + has_admin_role, + has_role_on_site, + can_restrict_on_site, +) +from ..utils.files import matching_file_subtypes +from . import mixins + +import filer + +logger = logging.getLogger(__name__) + + +def silence_error_if_missing_file(exception): + """ + Ugly way of checking if an exception describes a 'missing file'. + """ + missing_files_errs = ('no such file', 'does not exist',) + + def find_msg_in_error(msg): + return msg in str(exception).lower() + + if not any(map(find_msg_in_error, missing_files_errs)): + raise exception + + +class FileQuerySet(PolymorphicQuerySet): + def only(self, *fields): + fields = set(fields) + fields.update(["_file_size", "sha1", "is_public"]) + return super().only(*fields) + + # PBS-specific querysets + def readonly(self, user): + Folder = filer.models.foldermodels.Folder + return self.filter(folder__folder_type=Folder.CORE_FOLDER) + + def find_duplicates(self, file_obj): + return self.exclude(pk=file_obj.pk).filter(sha1=file_obj.sha1) + + def restricted(self, user): + sites = get_sites_without_restriction_perm(user) + if not sites: + return self.none() + return self.filter( + restricted=True, + folder__site__in=sites) + + def unrestricted(self, user): + sites = get_sites_without_restriction_perm(user) + if not sites: + return self + return self.exclude( + restricted=True, + folder__site__in=sites) class FileManager(PolymorphicManager): + queryset_class = FileQuerySet + + # Proxy all unknown method calls to the queryset + def __getattr__(self, name): + if name.startswith('__'): + return super(PolymorphicManager, self).__getattr__(self, name) + return getattr(self.all(), name) + def find_all_duplicates(self): - r = {} - for file_obj in self.all(): - if file_obj.sha1: - q = self.filter(sha1=file_obj.sha1) - if len(q) > 1: - r[file_obj.sha1] = q - return r + return {file_data['sha1']: file_data['count'] + for file_data in self.get_queryset().values('sha1').annotate( + count=Count('id')).filter(count__gt=1)} def find_duplicates(self, file_obj): return [i for i in self.exclude(pk=file_obj.pk).filter(sha1=file_obj.sha1)] -class File(PolymorphicModel, mixins.IconsMixin): - file_type = 'File' - _icon = "file" - folder = models.ForeignKey(Folder, verbose_name=_('folder'), related_name='all_files', - null=True, blank=True) - file = MultiStorageFileField(_('file'), null=True, blank=True, max_length=255) - _file_size = models.IntegerField(_('file size'), null=True, blank=True) +# PBS-specific managers for trash system +class AliveFileManager(FileManager): + def get_queryset(self): + return super().get_queryset().filter(deleted_at__isnull=True) - sha1 = models.CharField(_('sha1'), max_length=40, blank=True, default='') - has_all_mandatory_data = models.BooleanField(_('has all mandatory data'), default=False, editable=False) +class TrashFileManager(FileManager): + def get_queryset(self): + return super().get_queryset().filter(deleted_at__isnull=False) - original_filename = models.CharField(_('original filename'), max_length=255, blank=True, null=True) - name = models.CharField(max_length=255, null=True, blank=True, - verbose_name=_('name')) - description = models.TextField(null=True, blank=True, - verbose_name=_('description')) - owner = models.ForeignKey(auth_models.User, - related_name='owned_%(class)ss', - null=True, blank=True, verbose_name=_('owner')) +def is_public_default(): + # not using this setting directly as `is_public` default value + # so that Django doesn't generate new migrations upon setting change + return filer_settings.FILER_IS_PUBLIC_DEFAULT - uploaded_at = models.DateTimeField(_('uploaded at'), auto_now_add=True) - modified_at = models.DateTimeField(_('modified at'), auto_now=True) + +def mimetype_validator(value): + if not mimetypes.guess_extension(value): + msg = "'{mimetype}' is not a recognized MIME-Type." + raise ValidationError(msg.format(mimetype=value)) + + +@mixins.trashable +class File(PolymorphicModel, mixins.IconsMixin): + file_type = 'File' + _icon = 'file' + _file_data_changed_hint = None + + folder = models.ForeignKey( + 'filer.Folder', + verbose_name=_("folder"), + related_name='all_files', + null=True, + blank=True, + on_delete=models.CASCADE, + ) + + file = MultiStorageFileField( + _("file"), + null=True, + blank=True, + db_index=True, + max_length=1024, + ) + + _file_size = models.BigIntegerField( + _("file size"), + null=True, + blank=True, + ) + + sha1 = models.CharField( + _("sha1"), + max_length=40, + blank=True, + default='', + ) + + has_all_mandatory_data = models.BooleanField( + _("has all mandatory data"), + default=False, + editable=False, + ) + + original_filename = models.CharField( + _("original filename"), + max_length=255, + blank=True, + null=True, + ) + + name = models.CharField( + max_length=255, + null=True, + blank=True, + verbose_name=_("file name"), + help_text=_('Change the FILE name for an image in the cloud storage' + ' system; be sure to include the extension ' + '(.jpg or .png, for example) to ensure asset remains ' + 'valid.'), + ) + + title = models.CharField( + max_length=255, + null=True, + blank=True, + verbose_name=_("name"), + help_text=_('Used in the Photo Gallery plugin as a title or name for' + ' an image; not displayed via the image plugin.'), + ) + + description = models.TextField( + null=True, + blank=True, + verbose_name=_("description"), + help_text=_('Used in the Photo Gallery plugin as a description;' + ' not displayed via the image plugin.'), + ) + + owner = models.ForeignKey( + getattr(settings, 'AUTH_USER_MODEL', 'auth.User'), + related_name='owned_%(class)ss', + on_delete=models.SET_NULL, + null=True, + blank=True, + verbose_name=_("owner"), + ) + + uploaded_at = models.DateTimeField( + _("uploaded at"), + auto_now_add=True, + ) + + modified_at = models.DateTimeField( + _("modified at"), + auto_now=True, + ) is_public = models.BooleanField( default=filer_settings.FILER_IS_PUBLIC_DEFAULT, - verbose_name=_('Permissions disabled'), - help_text=_('Disable any permission checking for this ' +\ - 'file. File will be publicly accessible ' +\ - 'to anyone.')) + verbose_name=_("Permissions disabled"), + help_text=_("Disable any permission checking for this " + "file. File will be publicly accessible " + "to anyone."), + ) + + mime_type = models.CharField( + max_length=255, + help_text="MIME type of uploaded content", + validators=[mimetype_validator], + default='application/octet-stream', + ) + + # PBS-specific: restricted field + restricted = models.BooleanField( + _("Restrict Editors and Writers from being able to edit " + "or delete this asset"), default=False, + help_text=_('If this box is checked, ' + 'Editors and Writers will still be able to ' + 'view the asset, add it to a plugin or smart ' + 'snippet but will not be able to delete or ' + 'modify the current version of the asset.'), + ) + + # PBS-specific: trash managers + objects = AliveFileManager() + trash = TrashFileManager() + all_objects = FileManager() - objects = FileManager() + class Meta: + app_label = 'filer' + verbose_name = _("file") + verbose_name_plural = _("files") @classmethod def matches_file_type(cls, iname, ifile, request): return True # I match all files... + # Sentinel for fields whose previous value is unknown (deferred). + # Using a dedicated sentinel instead of substituting empty defaults + # prevents false positives in change-detection that could trigger + # unnecessary file copies/moves on storage. + _UNKNOWN = object() + def __init__(self, *args, **kwargs): - super(File, self).__init__(*args, **kwargs) - self._old_is_public = self.is_public + super().__init__(*args, **kwargs) + # PBS: Use __dict__ to avoid triggering deferred field loading + # which can cause recursion in Django 5.1+ (from_db calls __init__). + raw_is_public = self.__dict__.get('is_public', DEFERRED) + if raw_is_public is DEFERRED: + if self.pk is not None: + self._old_is_public = self.__class__.all_objects.filter( + pk=self.pk + ).values_list('is_public', flat=True).first() + else: + self._old_is_public = False + else: + self._old_is_public = raw_is_public + raw_sha1 = self.__dict__.get('sha1', DEFERRED) + self._old_sha1 = self._UNKNOWN if raw_sha1 is DEFERRED else raw_sha1 + self._force_commit = False + # see method _is_path_changed + raw_name = self.__dict__.get('name', DEFERRED) + self._old_name = self._UNKNOWN if raw_name is DEFERRED else raw_name + # For FileField, the raw value in __dict__ is the file name string + file_val = self.__dict__.get('file', '') + if file_val is DEFERRED: + file_val = '' + if file_val and hasattr(file_val, 'name'): + self._current_file_location = file_val.name + else: + self._current_file_location = file_val or '' + raw_folder_id = self.__dict__.get('folder_id', DEFERRED) + self._old_folder_id = self._UNKNOWN if raw_folder_id is DEFERRED else raw_folder_id + + @cached_property + def mime_maintype(self): + return self.mime_type.split('/')[0] + + @cached_property + def mime_subtype(self): + return self.mime_type.split('/')[1] + + def file_data_changed(self, post_init=False): + """ + This is called whenever self.file changes (including initial set in __init__). + Returns True if data related attributes were updated, False otherwise. + """ + if self._file_data_changed_hint is not None: + data_changed_hint = self._file_data_changed_hint + self._file_data_changed_hint = None + if not data_changed_hint: + return False + if post_init and self._file_size and self.sha1: + return False + try: + self._file_size = self.file.size + except: # noqa + self._file_size = None + try: + self.generate_sha1() + except Exception: + self.sha1 = '' + try: + self.mime_type = mimetypes.guess_type(self.file.name)[0] or 'application/octet-stream' + except Exception: + pass + return True + + def clean(self): + if self.name: + self.name = self.name.strip() + if "/" in self.name: + raise ValidationError( + "Slashes are not allowed in file names.") + extension = os.path.splitext(self.name)[1] + if not extension: + raise ValidationError( + "File name without extension is not allowed.") + + old_file_type = self.get_real_instance_class() + new_file_type = matching_file_subtypes(self.name, None, None)[0] + + if old_file_type is not new_file_type: + supported_extensions = getattr( + old_file_type, '_filename_extensions', []) + if supported_extensions: + err_msg = "File name (%s) for this %s should preserve " \ + "one of the supported extensions %s" % ( + self.name, old_file_type.file_type.lower(), + ', '.join(supported_extensions)) + else: + err_msg = "Extension %s is not allowed for this file " \ + "type." % (extension,) + raise ValidationError(err_msg) + + if self.folder: + entries = self.folder.entries_with_names([self.actual_name]) + if entries and any(entry.pk != self.pk for entry in entries): + raise ValidationError( + _('Current folder already contains a file named %s') % + self.actual_name) def _move_file(self): """ @@ -85,59 +378,70 @@ def _move_file(self): dst_storage = self.file.storages['private'] # delete the thumbnail - # We are toggling the is_public to make sure that easy_thumbnails can - # delete the thumbnails self.is_public = not self.is_public self.file.delete_thumbnails() self.is_public = not self.is_public - # This is needed because most of the remote File Storage backend do not - # open the file. src_file = src_storage.open(src_file_name) - src_file.open() - self.file = dst_storage.save(dst_file_name, - ContentFile(src_file.read())) + with src_file.open() as f: + content_file = ContentFile(f.read()) + self._file_data_changed_hint = False + self.file = dst_storage.save(dst_file_name, content_file) src_storage.delete(src_file_name) def _copy_file(self, destination, overwrite=False): """ Copies the file to a destination files and returns it. """ - if overwrite: - # If the destination file already exists default storage backend - # does not overwrite it but generates another filename. - # TODO: Find a way to override this behavior. raise NotImplementedError - src_file_name = self.file.name + src_file_name = self._current_file_location storage = self.file.storages['public' if self.is_public else 'private'] - # This is needed because most of the remote File Storage backend do not - # open the file. - src_file = storage.open(src_file_name) - src_file.open() - return storage.save(destination, ContentFile(src_file.read())) + if hasattr(storage, 'copy'): + storage.copy(src_file_name, destination) + else: + src_file = storage.open(src_file_name) + src_file.open() + file_content = src_file.read() + src_file.close() + if storage.exists(destination): + storage.delete(destination) + destination = storage.save(destination, + ContentFile(file_content, name=os.path.basename(destination))) + self._current_file_location = destination + self._old_name = self.name + self._old_folder_id = getattr(self.folder, 'id', None) + return destination def generate_sha1(self): sha = hashlib.sha1() self.file.seek(0) - sha.update(self.file.read()) + while True: + buf = self.file.read(104857600) + if not buf: + break + sha.update(buf) self.sha1 = sha.hexdigest() - # to make sure later operations can read the whole file self.file.seek(0) + # PBS-specific: set restricted from folder + def set_restricted_from_folder(self): + if self.folder and self.folder.restricted: + self.restricted = self.folder.restricted + def save(self, *args, **kwargs): + self.set_restricted_from_folder() # check if this is a subclass of "File" or not and set # _file_type_plugin_name if self.__class__ == File: - # what should we do now? - # maybe this has a subclass, but is being saved as a File instance - # anyway. do we need to go check all possible subclasses? pass elif issubclass(self.__class__, File): self._file_type_plugin_name = self.__class__.__name__ + # Ensure file metadata is computed on first save + if not self.sha1 and self.file: + self.file_data_changed() # cache the file size - # TODO: only do this if needed (depending on the storage backend the whole file will be downloaded) try: self._file_size = self.file.size except: @@ -145,51 +449,307 @@ def save(self, *args, **kwargs): if self._old_is_public != self.is_public and self.pk: self._move_file() self._old_is_public = self.is_public + # generate SHA1 hash - # TODO: only do this if needed (depending on the storage backend the whole file will be downloaded) try: self.generate_sha1() - except Exception, e: + except (IOError, TypeError, ValueError): pass - super(File, self).save(*args, **kwargs) + replaced_file = (self._old_sha1 is not self._UNKNOWN and + self._old_sha1 != self.sha1) + # Track old folder for cache invalidation when file moves between folders + old_folder_id = self._old_folder_id + if filer_settings.FOLDER_AFFECTS_URL and (self._is_path_changed() or replaced_file): + if replaced_file and not self._is_name_changed(): + self.name = None + self._force_commit = True + self.update_location_on_storage(*args, **kwargs) + else: + super().save(*args, **kwargs) + # Invalidate cache for the current folder + invalidate_folder_listing_cache_for_file(self) + # If file moved between folders, also invalidate the old folder + new_folder_id = getattr(self.folder, 'id', None) + if (old_folder_id is not self._UNKNOWN and + old_folder_id and old_folder_id != new_folder_id): + try: + old_folder = filer.models.foldermodels.Folder.all_objects.get( + id=old_folder_id) + invalidate_folder_listing_cache(old_folder) + except filer.models.foldermodels.Folder.DoesNotExist: + pass + save.alters_data = True - def delete(self, *args, **kwargs): - # Delete the model before the file - super(File, self).delete(*args, **kwargs) - # Delete the file if there are no other Files referencing it. - if not File.objects.filter(file=self.file.name, is_public=self.is_public).exists(): + def _is_name_changed(self): + """Check if the file name was explicitly changed by the user.""" + if self._old_name is self._UNKNOWN: + return False # can't determine change from deferred field + if self._old_name in ('', None): + return self.name not in ('', None) + return self._old_name != self.name + + def _is_path_changed(self): + """ + Used to detect if file location on storage should be updated or not. + """ + # If previous values are unknown (deferred), skip change-detection + # to avoid triggering unnecessary file copies/moves on storage. + if self._old_name is self._UNKNOWN or self._old_folder_id is self._UNKNOWN: + return False + + # check if file name changed + if self._old_name in ('', None): + name_changed = self.name not in ('', None) + else: + name_changed = self._old_name != self.name + + folder_changed = self._old_folder_id != getattr(self.folder, 'id', None) + return name_changed or folder_changed + + def _delete_thumbnails(self): + source = self.file.get_source_cache() + if source: + self.file.delete_thumbnails() + source.delete() + + def update_location_on_storage(self, *args, **kwargs): + old_location = self._current_file_location + self._delete_thumbnails() + if self._old_sha1 != self.sha1: + # actual file content needs to be replaced on storage prior to + # filer file instance save + if self._current_file_location: + self.file.storage.save(self._current_file_location, self.file) + else: + # New file — save to the computed target location directly + target = self.file.field.upload_to(self, self.upload_to_name) + saved_target = self.file.storage.save(target, self.file) + self._current_file_location = saved_target + self.file.name = saved_target + self._old_sha1 = self.sha1 + new_location = self.file.field.upload_to(self, self.upload_to_name) + storage = self.file.storage + + def copy_and_save(): + saved_as = self._copy_file(new_location) + assert saved_as == new_location, '%s %s' % (saved_as, new_location) + self._file_data_changed_hint = False + self.file = saved_as + super(File, self).save(*args, **kwargs) + + if self._force_commit: + try: + with transaction.atomic(savepoint=False): + copy_and_save() + except: + # delete the file from new_location if the db update failed + if old_location and old_location != new_location: + storage.delete(new_location) + raise + else: + # only delete the file on the old_location if all went OK + if old_location and old_location != new_location: + storage.delete(old_location) + else: + copy_and_save() + return new_location + + # PBS-specific: soft delete / trash system + def soft_delete(self, *args, **kwargs): + """ + Soft-delete: moves file to trash location on storage. + """ + deletion_time = kwargs.pop('deletion_time', django_timezone.now()) + to_trash = filer.utils.generate_filename.get_trash_path(self) + old_location, new_location = self.file.name, None + try: + new_location = self._copy_file(to_trash) + except Exception as e: + silence_error_if_missing_file(e) + if filer_settings.FILER_ENABLE_LOGGING: + logger.error('Error while trying to copy file: %s to %s.' % ( + old_location, to_trash), e) + else: + if not File.objects.exclude(pk=self.pk).filter( + file=old_location, is_public=self.is_public).exists(): + self.file.delete(False) + finally: + new_location = new_location or to_trash + File.objects.filter(pk=self.pk).update( + deleted_at=deletion_time, file=new_location) + self.deleted_at = deletion_time + self.file = new_location + # Invalidate cache for the folder this file was in + invalidate_folder_listing_cache_for_file(self) + + def hard_delete(self, *args, **kwargs): + """ + Hard-delete: removes from DB and storage. + """ + super().delete(*args, **kwargs) + if not File.objects.filter(file=self.file.name, + is_public=self.is_public).exists(): self.file.delete(False) + + def delete(self, *args, **kwargs): + super().delete_restorable(*args, **kwargs) delete.alters_data = True + def _set_valid_name_for_restore(self): + """ + Generates the first available name for restore. + """ + basename, extension = os.path.splitext(self.clean_actual_name) + if self.folder: + files = self.folder.files + else: + try: + owner = self.owner + except auth_models.User.DoesNotExist: + owner = None + if owner: + files = filer.models.tools.get_user_clipboard(self.owner).files.all() + else: + from filer.models.virtualitems import UnfiledImages + files = UnfiledImages().files + existing_file_names = [f.clean_actual_name for f in files] + i = 1 + while self.clean_actual_name in existing_file_names: + filename = "%s_%s%s" % (basename, i, extension) + if self.name in ('', None): + self.original_filename = filename + else: + self.name = filename + i += 1 + + def restore(self): + """ + Restores the file to its folder location. + """ + if self.folder_id: + Folder = filer.models.foldermodels.Folder + try: + self.folder + except Folder.DoesNotExist: + self.folder = Folder.trash.get(id=self.folder_id) + + self.folder.restore_path() + self.folder = filer.models.Folder.objects.get(id=self.folder_id) + + old_location, new_location = self.file.name, None + self._set_valid_name_for_restore() + destination = self.file.field.upload_to(self, self.upload_to_name) + try: + new_location = self._copy_file(destination) + except Exception as e: + silence_error_if_missing_file(e) + if filer_settings.FILER_ENABLE_LOGGING: + logger.error('Error while trying to copy file: %s to %s.' % ( + old_location, destination), e) + else: + self.file.delete(False) + finally: + new_location = new_location or destination + File.trash.filter(pk=self.pk).update( + deleted_at=None, file=new_location, + name=self.name, original_filename=self.original_filename) + self.deleted_at = None + self.file.name = new_location + if self.owner_id and not self.folder_id: + try: + clipboard = filer.models.tools.get_user_clipboard(self.owner) + clipboard.append_file(File.objects.get(id=self.id)) + except auth_models.User.DoesNotExist: + pass + # Invalidate cache for the folder this file was restored to + invalidate_folder_listing_cache_for_file(self) + + def __str__(self): + try: + name = self.pretty_logical_path + except: + name = self.actual_name + return name + @property def label(self): if self.name in ['', None]: text = self.original_filename or 'unnamed file' else: text = self.name - text = u"%s" % (text,) - return text + return f"{text}" + + def _cmp(self, a, b): + return (a > b) - (a < b) def __lt__(self, other): - return cmp(self.label.lower(), other.label.lower()) < 0 + return self._cmp(self.label.lower(), other.label.lower()) < 0 + + # PBS-specific: hash-based actual_name + @property + def actual_name(self): + if not self.sha1: + try: + self.generate_sha1() + except (IOError, TypeError, ValueError): + return self.clean_actual_name + try: + folder = self.folder.get_ancestors().first() + root_folder = getattr(folder, 'name', None) + except: + root_folder = None + if root_folder in filer_settings.FILER_NOHASH_ROOTFOLDERS: + name_fmt = '{actual_name}' + else: + name_fmt = '{hashcode}_{actual_name}' + name = name_fmt.format(hashcode=self.sha1[:10], + actual_name=self.clean_actual_name) + return name + @property + def upload_to_name(self): + """ + For normal files this is the actual name with the hash but clipboard + file upload locations are the clean names. + """ + if self.folder: + return self.actual_name + else: + return self.clean_actual_name + + @property + def clean_actual_name(self): + """The name displayed to the user.""" + if self.name in ('', None): + name = "%s" % (self.original_filename,) + else: + name = "%s" % (self.name,) + return name + + @property + def pretty_logical_path(self): + its_dir = self.logical_folder + if its_dir.is_root: + directory_path = '' + else: + directory_path = its_dir.pretty_logical_path + full_path = '{}{}{}'.format(directory_path, os.sep, self.actual_name) + return full_path + + # Upstream: permission methods def has_edit_permission(self, request): - return self.has_generic_permission(request, 'edit') + return request.user.has_perm("filer.change_file") and self.has_generic_permission(request, 'edit') def has_read_permission(self, request): return self.has_generic_permission(request, 'read') def has_add_children_permission(self, request): - return self.has_generic_permission(request, 'add_children') + return request.user.has_perm("filer.add_file") and self.has_generic_permission(request, 'add_children') def has_generic_permission(self, request, permission_type): - """ - Return true if the current user has permission on this - image. Return the string 'ALL' if the user has all rights. - """ user = request.user - if not user.is_authenticated(): + if not user.is_authenticated: return False elif user.is_superuser: return True @@ -200,46 +760,67 @@ def has_generic_permission(self, request, permission_type): else: return False - def __unicode__(self): - if self.name in ('', None): - text = u"%s" % (self.original_filename,) - else: - text = u"%s" % (self.name,) - return text - - def get_admin_url_path(self): - return urlresolvers.reverse( - 'admin:%s_%s_change' % (self._meta.app_label, - self._meta.module_name,), + def get_admin_url(self, action): + return reverse( + 'admin:{}_{}_{}'.format( + self._meta.app_label, + self._meta.model_name, + action + ), args=(self.pk,) ) - @property - def file_ptr(self): - """ - Evil hack to get around the cascade delete problem with django_polymorphic. - Prevents ``AttributeError: 'File' object has no attribute 'file_ptr'``. - This is only a workaround for one level of subclassing. The hierarchy of - object in the admin delete view is wrong, but at least it works. - """ - return self + def get_admin_url_path(self): + return self.get_admin_url("change") + + def get_admin_change_url(self): + return self.get_admin_url("change") + + def get_admin_expand_view_url(self): + return self.get_admin_url("expand") + + def get_admin_delete_url(self): + return self.get_admin_url("delete") @property def url(self): """ to make the model behave like a file field """ + if self.is_in_trash(): + return '' try: r = self.file.url - except: + except: # noqa r = '' - return r + from filer.utils.cdn import get_cdn_url + return get_cdn_url(self, r) + + @property + def canonical_time(self): + if settings.USE_TZ: + return int((self.uploaded_at - datetime(1970, 1, 1, 1, tzinfo=timezone.utc)).total_seconds()) + else: + return int((self.uploaded_at - datetime(1970, 1, 1, 1)).total_seconds()) + + @property + def canonical_url(self): + url = '' + if self.file and self.is_public: + try: + url = reverse('canonical', kwargs={ + 'uploaded_at': self.canonical_time, + 'file_id': self.id + }) + except NoReverseMatch: + pass + return url @property def path(self): try: return self.file.path - except: + except: # noqa return "" @property @@ -255,10 +836,6 @@ def extension(self): @property def logical_folder(self): - """ - if this file is not in a specific folder return the Special "unfiled" - Folder object - """ if not self.folder: from filer.models.virtualitems import UnfiledImages return UnfiledImages() @@ -267,10 +844,6 @@ def logical_folder(self): @property def logical_path(self): - """ - Gets logical path of the folder in the tree structure. - Used to generate breadcrumbs - """ folder_path = [] if self.folder: folder_path.extend(self.folder.get_ancestors()) @@ -279,9 +852,65 @@ def logical_path(self): @property def duplicates(self): - return File.objects.find_duplicates(self) + return list(File.objects.find_duplicates(self)) - class Meta: - app_label = 'filer' - verbose_name = _('file') - verbose_name_plural = _('files') + # PBS-specific: site/core permission methods + def is_core(self): + if self.folder: + return self.folder.is_core() + return False + + def is_readonly_for_user(self, user): + if self.folder: + return self.folder.is_readonly_for_user(user) + return False + + def is_restricted_for_user(self, user): + perm = 'filer.can_restrict_operations' + return (self.restricted and ( + not (user.has_perm(perm, self) or user.has_perm(perm)) or + not can_restrict_on_site(user, self.folder.site))) + + def can_change_restricted(self, user): + perm = 'filer.can_restrict_operations' + if not user.has_perm(perm, self) and not user.has_perm(perm): + return False + if not self.folder: + return False + if not can_restrict_on_site(user, self.folder.site): + return False + if self.folder.restricted == self.restricted == True: + return False + if self.folder.restricted == self.restricted == False: + return True + if self.folder.restricted == True and self.restricted == False: + raise IntegrityError( + 'Re-save folder %s to fix restricted property' % ( + self.folder.pretty_logical_path)) + return True + + def has_change_permission(self, user): + if not self.folder: + return True + if self.is_readonly_for_user(user): + return True + if not self.folder.site and has_admin_role(user): + return True + if self.folder.site: + can_change_file = (user.has_perm('filer.change_file', self) or + user.has_perm('filer.change_file')) + return can_change_file and has_role_on_site(user, self.folder.site) + return False + + def has_delete_permission(self, user): + if not self.folder: + return True + if self.is_readonly_for_user(user): + return False + if not self.folder.site and has_admin_role(user): + return True + if self.folder.site: + can_delete_file = (user.has_perm('filer.delete_file', self) or + user.has_perm('filer.delete_file')) + return can_delete_file and has_role_on_site(user, self.folder.site) + return False diff --git a/filer/models/foldermodels.py b/filer/models/foldermodels.py index ddedea1e4..0e497062c 100644 --- a/filer/models/foldermodels.py +++ b/filer/models/foldermodels.py @@ -1,31 +1,48 @@ -#-*- coding: utf-8 -*- +import itertools +import logging + +from django.conf import settings from django.contrib.auth import models as auth_models -from django.core import urlresolvers +from django.contrib.sites.models import Site from django.core.exceptions import ValidationError -from django.db import models -from django.db.models import Q -from django.utils.translation import ugettext_lazy as _ -from filer.models import mixins -from filer import settings as filer_settings +from django.db import models, IntegrityError, transaction +from django.db.models import Q, query, signals, DEFERRED +from django.dispatch import receiver +from django.urls import reverse +from django.utils.functional import cached_property +from django.utils.html import format_html, format_html_join +from django.utils.translation import gettext +from django.utils.translation import gettext_lazy as _ +from django.utils import timezone +from urllib.parse import quote import mptt +from .. import settings as filer_settings +from ..cache import get_folder_permission_cache, update_folder_permission_cache +from ..utils.cache import invalidate_folder_listing_cache +from ..utils.cms_roles import ( + get_sites_for_user, + get_sites_without_restriction_perm, + has_admin_role, + has_admin_role_on_site, + has_role_on_site, + can_restrict_on_site, +) +from . import mixins -class FolderManager(models.Manager): - def with_bad_metadata(self): - return self.get_query_set().filter(has_all_mandatory_data=False) +import filer + + +logger = logging.getLogger(__name__) class FolderPermissionManager(models.Manager): """ - Theses methods are called by introspection from "has_generic_permisison" on + These methods are called by introspection from "has_generic_permission" on the folder model. """ def get_read_id_list(self, user): - """ - Give a list of a Folders where the user has read rights or the string - "All" if the user has all rights. - """ return self.__get_id_list(user, "can_read") def get_edit_id_list(self, user): @@ -37,17 +54,20 @@ def get_add_children_id_list(self, user): def __get_id_list(self, user, attr): if user.is_superuser or not filer_settings.FILER_ENABLE_PERMISSIONS: return 'All' + cached_id_list = get_folder_permission_cache(user, attr) + if cached_id_list: + return cached_id_list + allow_list = set() deny_list = set() group_ids = user.groups.all().values_list('id', flat=True) q = Q(user=user) | Q(group__in=group_ids) | Q(everybody=True) - perms = self.filter(q).order_by('folder__tree_id', 'folder__level', - 'folder__lft') + perms = self.filter(q) + for perm in perms: p = getattr(perm, attr) if p is None: - # Not allow nor deny, we continue with the next permission continue if not perm.folder: @@ -57,7 +77,6 @@ def __get_id_list(self, user, attr): allow_list.update(Folder.objects.all().values_list('id', flat=True)) else: deny_list.update(Folder.objects.all().values_list('id', flat=True)) - continue folder_id = perm.folder.id @@ -67,16 +86,101 @@ def __get_id_list(self, user, attr): else: deny_list.add(folder_id) - if perm.type == FolderPermission.CHILDREN: + if perm.type in [FolderPermission.ALL, FolderPermission.CHILDREN]: if p == FolderPermission.ALLOW: - allow_list.update(perm.folder.get_descendants().values_list('id', flat=True)) + allow_list.update(perm.folder.get_descendants_ids()) else: - deny_list.update(perm.folder.get_descendants().values_list('id', flat=True)) + deny_list.update(perm.folder.get_descendants_ids()) + + id_list = allow_list - deny_list + update_folder_permission_cache(user, attr, id_list) + return id_list + + +# PBS-specific: chainable queryset mixin with trash/restriction support +class FoldersChainableQuerySetMixin: + + def with_bad_metadata(self): + return self.filter(has_all_mandatory_data=False) + + def valid_destinations(self, user): + available_sites = get_sites_for_user(user) + core_folders = Q(folder_type=Folder.CORE_FOLDER) + no_site = Q(site__isnull=True) + shared_folders = ~Q(site__in=available_sites) + return self.exclude(core_folders | no_site | shared_folders) + + def readonly(self, user): + core_folders = Q(folder_type=Folder.CORE_FOLDER) + available_sites = get_sites_for_user(user) + shared_folders = Q(~Q(site__in=available_sites) & + Q(shared__in=available_sites)) + readonly_folders = Q(core_folders | shared_folders) + return self.filter(readonly_folders) + + def restricted_descendants(self, user): + sites = get_sites_without_restriction_perm(user) + if not sites: + return self.none() + descendant_filter = None + for node in self: + q = Q(**{ + 'tree_id': node.tree_id, + 'lft__gt': node.lft - 1, + 'rght__lt': node.rght + 1, + }) + if descendant_filter is None: + descendant_filter = q + else: + descendant_filter |= q + if not descendant_filter: + return self.none() + restr_q = Q(Q(restricted=True) | Q( + Q(all_files__restricted=True) & + Q(all_files__deleted_at__isnull=True))) + restr_q &= Q(site__in=sites) + return self.model.objects.filter( + descendant_filter).filter(restr_q).distinct() + + def unrestricted(self, user): + sites = get_sites_without_restriction_perm(user) + if not sites: + return self + return self.exclude(restricted=True, site__in=sites) + + def in_trash(self): + return self.filter(deleted_at__isnull=False) + + def alive(self): + return self.filter(deleted_at__isnull=True) + + +class FolderQueryset(query.QuerySet, FoldersChainableQuerySetMixin): + pass + + +class FolderManager(models.Manager): + + def get_queryset(self): + return FolderQueryset(self.model, using=self._db) + + def __getattr__(self, name): + if name.startswith('__'): + return super(FolderManager, self).__getattr__(self, name) + return getattr(self.get_queryset(), name) + + +class AliveFolderManager(FolderManager): + def get_queryset(self): + return FolderQueryset(self.model, using=self._db).alive() - # Deny has precedence over allow - return allow_list - deny_list +class TrashFolderManager(FolderManager): + def get_queryset(self): + return FolderQueryset(self.model, using=self._db).in_trash() + +@mixins.trashable class Folder(models.Model, mixins.IconsMixin): """ Represents a Folder that things (files) can be put into. Folders are *NOT* @@ -92,20 +196,317 @@ class Folder(models.Model, mixins.IconsMixin): can_have_subfolders = True _icon = 'plainfolder' - parent = models.ForeignKey('self', verbose_name=('parent'), null=True, blank=True, - related_name='children') - name = models.CharField(_('name'), max_length=255) + # PBS-specific: folder types + SITE_FOLDER = 0 + CORE_FOLDER = 1 + + FOLDER_TYPES = { + SITE_FOLDER: 'Site Folder', + CORE_FOLDER: 'Core Folder', + } + + parent = models.ForeignKey( + 'self', + verbose_name=_('parent'), + null=True, + blank=True, + related_name='children', + on_delete=models.CASCADE, + ) - owner = models.ForeignKey(auth_models.User, verbose_name=('owner'), - related_name='filer_owned_folders', - null=True, blank=True) + name = models.CharField( + _('name'), + max_length=255, + ) - uploaded_at = models.DateTimeField(_('uploaded at'), auto_now_add=True) + owner = models.ForeignKey( + getattr(settings, 'AUTH_USER_MODEL', 'auth.User'), + verbose_name=_('owner'), + related_name='filer_owned_folders', + on_delete=models.SET_NULL, + null=True, + blank=True, + ) - created_at = models.DateTimeField(_('created at'), auto_now_add=True) - modified_at = models.DateTimeField(_('modified at'),auto_now=True) + uploaded_at = models.DateTimeField( + _('uploaded at'), + auto_now_add=True, + ) + + created_at = models.DateTimeField( + _('created at'), + auto_now_add=True, + ) + + modified_at = models.DateTimeField( + _('modified at'), + auto_now=True, + ) + + # PBS-specific fields + folder_type = models.IntegerField( + choices=list(FOLDER_TYPES.items()), + default=SITE_FOLDER, + ) - objects = FolderManager() + site = models.ForeignKey( + Site, + null=True, + blank=True, + on_delete=models.SET_NULL, + help_text=_("Select the site which will use this folder."), + ) + + restricted = models.BooleanField( + _("Restrict Editors and Writers from being able to edit " + "or delete anything from this folder"), + default=False, + help_text=_('If this box is checked, ' + 'Editors and Writers will still be able to ' + 'view this folder assets, add them to a plugin or smart ' + 'snippet but will not be able to delete or ' + 'modify the current version of the assets.'), + ) + + shared = models.ManyToManyField( + Site, + blank=True, + related_name='shared', + verbose_name=_("Share folder with sites"), + help_text=_("All the sites which you share this folder with will " + "be able to use this folder on their pages, with all of " + "its assets. However, they will not be able to change, " + "delete or move it, not even add new assets."), + ) + + # PBS-specific: trash managers + objects = AliveFolderManager() + trash = TrashFolderManager() + all_objects = FolderManager() + + class Meta: + ordering = ('name',) + permissions = ( + ("can_use_directory_listing", "Can use directory listing"), + ("can_restrict_operations", "Can restrict files or folders"), + ) + app_label = 'filer' + verbose_name = _("Folder") + verbose_name_plural = _("Folders") + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + if self.__dict__.get('name', DEFERRED) is not DEFERRED: + self._old_name = self.name + if self.__dict__.get('parent_id', DEFERRED) is not DEFERRED: + self._old_parent_id = self.parent_id + + def __str__(self): + try: + name = self.pretty_logical_path + except: + name = self.name + return name + + def __repr__(self): + return f'<{self.__class__.__name__}(pk={self.pk}): {self.name}>' + + def clean(self): + if self.name == filer.models.clipboardmodels.Clipboard.folder_name: + raise ValidationError( + _('%s is reserved for internal use. ' + 'Please choose a different name') % self.name) + + if self.name and "/" in self.name: + raise ValidationError("Slashes are not allowed in folder names.") + + duplicate_folders_q = Folder.objects.filter( + parent=self.parent_id, + name=self.name) + if self.pk: + duplicate_folders_q = duplicate_folders_q.exclude(pk=self.pk) + + if duplicate_folders_q.exists(): + raise ValidationError( + 'This folder name is already in use. ' + 'Please choose a different name.') + + if not self.parent: + if (self.folder_type == Folder.SITE_FOLDER and + not self.site): + raise ValidationError('Folder is a Site folder. ' + 'Site is required.') + if (self.folder_type == Folder.CORE_FOLDER and not self.parent and + self.site): + raise ValidationError('Folder is a Core folder. ' + 'Site must be empty.') + + def set_metadata_from_parent(self): + if self.parent: + self.site = self.parent.site + self.folder_type = self.parent.folder_type + if self.parent.restricted: + self.restricted = self.parent.restricted + + if self.is_core(): + self.site = None + + self._update_descendants = self.has_new_metadata_value() + + def has_new_metadata_value(self): + if not self.pk: + return True + metadata_fields = ['restricted', 'site_id', 'folder_type'] + old_metadata = self.__class__.all_objects.\ + filter(pk=self.pk).values(*metadata_fields).get() + for field in metadata_fields: + if getattr(self, field) != old_metadata[field]: + return True + return False + + def is_affecting_file_paths(self): + return (self._old_name != self.name or + self._old_parent_id != getattr(self, 'parent_id', None)) + + def update_descendants_metadata(self): + descendants = None + if self._update_descendants: + descendants = self.get_descendants() + descendants.update( + folder_type=self.folder_type, site=self.site, + restricted=self.restricted) + desc_ids = [desc.pk for desc in descendants] + if self.pk: + desc_ids.append(self.pk) + file_mgr = filer.models.filemodels.File.all_objects + file_mgr.filter( + folder__in=desc_ids).update(restricted=self.restricted) + + if self.parent: + parent_shared_sites = self.parent.shared.values_list( + 'id', flat=True) + instance_shared_sites = self.shared.values_list('id', flat=True) + if set(instance_shared_sites) != set(parent_shared_sites): + shared_sites = self.parent.shared.all() + self.shared.set(shared_sites) + descendants = descendants or self.get_descendants() + for desc_folder in descendants: + desc_folder.shared.set(shared_sites) + + def save(self, *args, **kwargs): + if not filer_settings.FOLDER_AFFECTS_URL: + self.set_metadata_from_parent() + super().save(*args, **kwargs) + self.update_descendants_metadata() + invalidate_folder_listing_cache(self) + return + + storages = [] + old_locations = [] + new_locations = [] + + def delete_from_locations(locations, storages): + for location, storage in zip(locations, storages): + storage.delete(location) + + try: + with transaction.atomic(savepoint=False): + self.set_metadata_from_parent() + super().save(*args, **kwargs) + self.update_descendants_metadata() + if self.is_affecting_file_paths(): + desc_ids = list(self.get_descendants( + include_self=True).values_list('id', flat=True)) + file_mgr = filer.models.filemodels.File.objects + all_files = file_mgr.filter(folder__in=desc_ids) + for f in all_files: + old_location = f.file.name + new_location = f.update_location_on_storage() + if old_location != new_location: + storages.append(f.file.storage) + old_locations.append(old_location) + new_locations.append(new_location) + except: + delete_from_locations(new_locations, storages) + raise + else: + delete_from_locations(old_locations, storages) + invalidate_folder_listing_cache(self) + + # PBS-specific: trash methods + def soft_delete(self): + deletion_time = timezone.now() + desc_ids = list(self.get_descendants( + include_self=True).values_list('id', flat=True)) + file_mgr = filer.models.filemodels.File.objects + files_qs = file_mgr.filter(folder__in=desc_ids) + for filer_file in files_qs: + filer_file.soft_delete(deletion_time=deletion_time) + Folder.objects.filter( + id__in=desc_ids).update(deleted_at=deletion_time) + self.deleted_at = deletion_time + # Invalidate cache for this folder and its parent + invalidate_folder_listing_cache(self) + + def hard_delete(self): + desc_ids = list(self.get_descendants( + include_self=True).values_list('id', flat=True)) + file_mgr = filer.models.filemodels.File.all_objects + for file_obj in file_mgr.filter(folder__in=desc_ids): + file_obj.hard_delete() + super().delete() + + def delete(self, *args, **kwargs): + super().delete_restorable(*args, **kwargs) + delete.alters_data = True + + def _generate_valid_name_for_restore(self): + name = self.name + i = 1 + while self.get_siblings().filter( + deleted_at__isnull=True, name=name).exists(): + name = "%s_%s" % (self.name, i) + i += 1 + return name + + def restore_path(self): + trashed_ancestors = self.get_ancestors(include_self=True).filter( + deleted_at__isnull=False) + first_node_trashed = trashed_ancestors[:1] + if first_node_trashed: + first_node_trashed = first_node_trashed[0] + new_name = first_node_trashed._generate_valid_name_for_restore() + if new_name != first_node_trashed.name: + Folder.trash.filter( + id=first_node_trashed.id).update(name=new_name) + trashed_ancestors.update(deleted_at=None) + + def restore(self): + self.restore_path() + desc_ids = [self.id] + descendants = self.get_descendants(include_self=True).filter( + deleted_at__isnull=False) + for descendant in descendants: + new_name = descendant._generate_valid_name_for_restore() + Folder.trash.filter(id=descendant.id).update( + deleted_at=None, name=new_name) + desc_ids.append(descendant.id) + file_mgr = filer.models.filemodels.File.trash + files_qs = file_mgr.filter(folder__in=desc_ids) + for filer_file in files_qs: + filer_file.restore() + self.deleted_at = None + # Invalidate cache for this folder and its parent + invalidate_folder_listing_cache(self) + + @property + def trashed_file_count(self): + file_mgr = filer.models.filemodels.File.trash + return file_mgr.filter(folder_id=self.id).count() + + @property + def trashed_children_count(self): + return Folder.trash.filter(parent_id=self.id).count() @property def file_count(self): @@ -123,42 +524,75 @@ def children_count(self): def item_count(self): return self.file_count + self.children_count + @property + def trashed_files(self): + trash_file_mgr = filer.models.filemodels.File.trash + if not self.pk: + return trash_file_mgr.none() + return trash_file_mgr.filter(folder=self).order_by( + 'title', 'name', 'original_filename') + @property def files(self): - return self.all_files.all() + return filer.models.File.objects.filter(folder=self) + + def entries_with_names(self, names): + q = Q(name__in=names) + q |= Q(original_filename__in=names) & (Q(name__isnull=True) | Q(name='')) + files_with_names = filer.models.File.objects.filter( + folder=self).filter(q) + folders_with_names = Folder.objects.filter( + parent=self, name__in=names) + return list(itertools.chain(files_with_names, folders_with_names)) + + def pretty_path_entries(self): + subdirs = self.get_descendants(include_self=True).filter( + deleted_at__isnull=True) + subdir_files = filer.models.File.objects.filter(folder__in=subdirs) + file_paths = [x.pretty_logical_path for x in subdir_files] + dir_paths = [x.pretty_logical_path for x in subdirs] + return file_paths + dir_paths + + def get_descendants_ids(self): + desc = [] + for child in self.children.all(): + desc.append(child.id) + desc.extend(child.get_descendants_ids()) + return desc @property def logical_path(self): - """ - Gets logical path of the folder in the tree structure. - Used to generate breadcrumbs - """ folder_path = [] - if self.parent: - folder_path.extend(self.parent.get_ancestors()) - folder_path.append(self.parent) + try: + if self.parent: + folder_path.extend(self.parent.get_ancestors( + include_self=True).filter(deleted_at__isnull=True)) + except Folder.DoesNotExist: + pass return folder_path @property def pretty_logical_path(self): - return u"/%s" % u"/".join([f.name for f in self.logical_path+[self]]) + return "/%s" % "/".join([f.name + for f in self.logical_path + [self]]) + + @property + def quoted_logical_path(self): + return quote(self.pretty_logical_path) + # Upstream permission methods def has_edit_permission(self, request): - return self.has_generic_permission(request, 'edit') + return request.user.has_perm("filer.change_folder") and self.has_generic_permission(request, 'edit') def has_read_permission(self, request): return self.has_generic_permission(request, 'read') def has_add_children_permission(self, request): - return self.has_generic_permission(request, 'add_children') + return request.user.has_perm("filer.change_folder") and self.has_generic_permission(request, 'add_children') def has_generic_permission(self, request, permission_type): - """ - Return true if the current user has permission on this - folder. Return the string 'ALL' if the user has all rights. - """ user = request.user - if not user.is_authenticated(): + if not user.is_authenticated: return False elif user.is_superuser: return True @@ -172,8 +606,6 @@ def has_generic_permission(self, request, permission_type): self.permission_cache = { 'user': request.user, } - - # This calls methods on the manager i.e. get_read_id_list() func = getattr(FolderPermission.objects, "get_%s_id_list" % permission_type) permission = func(user) @@ -186,16 +618,20 @@ def has_generic_permission(self, request, permission_type): self.permission_cache[permission_type] = self.id in permission return self.permission_cache[permission_type] + def get_admin_change_url(self): + return reverse('admin:filer_folder_change', args=(self.id,)) + def get_admin_url_path(self): - return urlresolvers.reverse('admin:filer_folder_change', - args=(self.id,)) + return reverse('admin:filer_folder_change', args=(self.id,)) def get_admin_directory_listing_url_path(self): - return urlresolvers.reverse('admin:filer-directory_listing', - args=(self.id,)) + return reverse('admin:filer-directory_listing', args=(self.id,)) - def __unicode__(self): - return u"%s" % (self.name,) + def get_admin_delete_url(self): + return reverse( + f'admin:{self._meta.app_label}_{self._meta.model_name}_delete', + args=(self.pk,) + ) def contains_folder(self, folder_name): try: @@ -204,14 +640,87 @@ def contains_folder(self, folder_name): except Folder.DoesNotExist: return False - class Meta: - unique_together = (('parent', 'name'),) - ordering = ('name',) - permissions = (("can_use_directory_listing", - "Can use directory listing"),) - app_label = 'filer' - verbose_name = _("Folder") - verbose_name_plural = _("Folders") + @property + def actual_name(self): + return self.name + + @property + def get_folder_type_display(self): + if self.shared.exists(): + return 'Shared by site' + return Folder.FOLDER_TYPES[self.folder_type] + + # PBS-specific: site/core permission methods + def is_core(self): + return self.folder_type == Folder.CORE_FOLDER + + def is_readonly_for_user(self, user): + return self.is_core() or ( + self.site and not has_role_on_site(user, self.site) and + self.shared.filter(id__in=get_sites_for_user(user)).exists()) + + def is_restricted_for_user(self, user): + perm = 'filer.can_restrict_operations' + return (self.restricted and ( + not (user.has_perm(perm, self) or user.has_perm(perm)) or + not can_restrict_on_site(user, self.site))) + + def can_change_restricted(self, user): + perm = 'filer.can_restrict_operations' + if (not (user.has_perm(perm, self) or user.has_perm(perm)) or + not can_restrict_on_site(user, self.site)): + return False + if not self.parent: + return True + if self.parent.restricted == self.restricted == True: + return False + if self.parent.restricted == self.restricted == False: + return True + if self.parent.restricted == True and self.restricted == False: + raise IntegrityError( + 'Re-save folder %s to fix restricted property' % ( + self.parent.pretty_logical_path)) + return True + + def has_add_permission(self, user): + if (self.is_readonly_for_user(user) or + self.is_restricted_for_user(user)): + return False + if not self.site and has_admin_role(user): + return True + if not self.site or not has_role_on_site(user, self.site): + return False + perm = 'filer.add_folder' + return user.has_perm(perm, self.site) or user.has_perm(perm) + + def has_change_permission(self, user): + if (self.is_readonly_for_user(user) or + self.is_restricted_for_user(user)): + return False + if not self.site and has_admin_role(user): + return True + if not self.site: + return False + if not self.parent: + return has_admin_role_on_site(user, self.site) + perm = 'filer.change_folder' + return ((user.has_perm(perm, self.site) or user.has_perm(perm)) and + has_role_on_site(user, self.site)) + + def has_delete_permission(self, user): + if (self.is_readonly_for_user(user) or + self.is_restricted_for_user(user)): + return False + if not self.site and user.is_superuser: + return True + if not self.site: + return False + if not self.parent: + return has_admin_role_on_site(user, self.site) + perm = 'filer.delete_folder' + return ((user.has_perm(perm, self.site) or user.has_perm(perm)) and + has_role_on_site(user, self.site)) + # MPTT registration try: @@ -220,6 +729,23 @@ class Meta: pass +@receiver(signals.m2m_changed, sender=Folder.shared.through) +def update_shared_sites_for_descendants(instance, **kwargs): + """ + Makes sure that folders keep all shared sites from their root folder. + """ + action = kwargs['action'] + if not action.startswith('post_') or instance.parent_id: + return + + instance = Folder.all_objects.get(id=instance.id) + sites = instance.shared.all() + descendants = instance.get_descendants() + for desc_folder in descendants: + desc_folder.shared.set(sites) + + +# Upstream: FolderPermission model class FolderPermission(models.Model): ALL = 0 THIS = 1 @@ -228,72 +754,139 @@ class FolderPermission(models.Model): ALLOW = 1 DENY = 0 - TYPES = ( - (ALL, _('all items')), - (THIS, _('this item only')), - (CHILDREN, _('this item and all children')), + TYPES = [ + (ALL, _("all items")), + (THIS, _("this item only")), + (CHILDREN, _("this item and all children")), + ] + + PERMISIONS = [ + (None, _("inherit")), + (ALLOW, _("allow")), + (DENY, _("deny")), + ] + + folder = models.ForeignKey( + Folder, + verbose_name=("folder"), + null=True, + blank=True, + on_delete=models.CASCADE, ) - PERMISIONS = ( - (ALLOW, _('allow')), - (DENY, _('deny')), + type = models.SmallIntegerField( + _("type"), + choices=TYPES, + default=ALL, ) - folder = models.ForeignKey(Folder, verbose_name=('folder'), null=True, blank=True) + user = models.ForeignKey( + getattr(settings, 'AUTH_USER_MODEL', 'auth.User'), + related_name="filer_folder_permissions", + on_delete=models.SET_NULL, + verbose_name=_("user"), + blank=True, + null=True, + ) - type = models.SmallIntegerField(_('type'), choices=TYPES, default=ALL) - user = models.ForeignKey(auth_models.User, - related_name="filer_folder_permissions", - verbose_name=_("user"), blank=True, null=True) - group = models.ForeignKey(auth_models.Group, - related_name="filer_folder_permissions", - verbose_name=_("group"), blank=True, null=True) - everybody = models.BooleanField(_("everybody"), default=False) + group = models.ForeignKey( + auth_models.Group, + related_name="filer_folder_permissions", + verbose_name=_("group"), + blank=True, + null=True, + on_delete=models.CASCADE, + ) - can_edit = models.SmallIntegerField(_("can edit"), choices=PERMISIONS, blank=True, null=True, default=None) - can_read = models.SmallIntegerField(_("can read"), choices=PERMISIONS, blank=True, null=True, default=None) - can_add_children = models.SmallIntegerField(_("can add children"), choices=PERMISIONS, blank=True, null=True, default=None) + everybody = models.BooleanField( + _("everybody"), + default=False, + ) + + can_read = models.SmallIntegerField( + _("can read"), + choices=PERMISIONS, + blank=True, + null=True, + default=None, + ) + + can_edit = models.SmallIntegerField( + _("can edit"), + choices=PERMISIONS, + blank=True, + null=True, + default=None, + ) + + can_add_children = models.SmallIntegerField( + _("can add children"), + choices=PERMISIONS, + blank=True, + null=True, + default=None, + ) + + class Meta: + verbose_name = _('folder permission') + verbose_name_plural = _('folder permissions') + app_label = 'filer' objects = FolderPermissionManager() - def __unicode__(self): - if self.folder: - name = u'%s' % self.folder - else: - name = u'All Folders' + def __str__(self): + return self.pretty_logical_path - ug = [] - if self.everybody: - ug.append('Everybody') - else: - if self.group: - ug.append(u"Group: %s" % self.group) - if self.user: - ug.append(u"User: %s" % self.user) - usergroup = " ".join(ug) - perms = [] - for s in ['can_edit', 'can_read', 'can_add_children']: - perm = getattr(self, s) - if perm == self.ALLOW: - perms.append(s) - elif perm == self.DENY: - perms.append('!%s' % s) - perms = ', '.join(perms) - return u"Folder: '%s'->%s [%s] [%s]" % ( - name, unicode(self.TYPES[self.type][1]), - perms, usergroup) + def __repr__(self): + return f'<{self.__class__.__name__}(pk={self.pk}): folder="{self.pretty_logical_path}">' def clean(self): if self.type == self.ALL and self.folder: - raise ValidationError('Folder cannot be selected with type "all items".') + raise ValidationError(_('Folder cannot be selected with type "all items".')) if self.type != self.ALL and not self.folder: - raise ValidationError('Folder has to be selected when type is not "all items".') + raise ValidationError(_('Folder has to be selected when type is not "all items".')) if self.everybody and (self.user or self.group): - raise ValidationError('User or group cannot be selected together with "everybody".') + raise ValidationError(_('User or group cannot be selected together with "everybody".')) if not self.user and not self.group and not self.everybody: - raise ValidationError('At least one of user, group, or "everybody" has to be selected.') + raise ValidationError(_('At least one of user, group, or "everybody" has to be selected.')) - class Meta: - verbose_name = _('folder permission') - verbose_name_plural = _('folder permissions') - app_label = 'filer' + @cached_property + def pretty_logical_path(self): + if self.folder: + return self.folder.pretty_logical_path + return gettext("All Folders") + + pretty_logical_path.short_description = _("Logical Path") + + @cached_property + def who(self): + parts = [] + if self.user: + parts.append(_("User: {user}").format(user=self.user)) + if self.group: + parts.append(_("Group: {group}").format(group=self.group)) + if self.everybody: + parts.append(_("Everybody")) + if parts: + return format_html_join("; ", '{}', ((p,) for p in parts)) + return '–' + + who.short_description = _("Who") + + @cached_property + def what(self): + mapping = { + 'can_edit': _("Edit"), + 'can_read': _("Read"), + 'can_add_children': _("Add children"), + } + perms = [] + for key, text in mapping.items(): + perm = getattr(self, key) + if perm == self.ALLOW: + perms.append(text) + elif perm == self.DENY: + perms.append('\u0336'.join(text) + '\u0336') + return format_html_join(", ", '{}', ((p,) for p in perms)) + + what.short_description = _("What") diff --git a/filer/models/imagemodels.py b/filer/models/imagemodels.py index 528b15119..e385cf595 100644 --- a/filer/models/imagemodels.py +++ b/filer/models/imagemodels.py @@ -1,203 +1,90 @@ -#-*- coding: utf-8 -*- import logging - -try: - from PIL import Image as PILImage -except ImportError: - try: - import Image as PILImage - except ImportError: - raise ImportError("The Python Imaging Library was not found.") from datetime import datetime -from django.core import urlresolvers -from django.db import models -from django.utils.translation import ugettext_lazy as _ -from filer import settings as filer_settings -from filer.models.filemodels import File -from filer.utils.filer_easy_thumbnails import FilerThumbnailer -from filer.utils.pil_exif import get_exif_for_file -import os - -logger = logging.getLogger("filer") - -class Image(File): - SIDEBAR_IMAGE_WIDTH = 210 - DEFAULT_THUMBNAILS = { - 'admin_clipboard_icon': {'size': (32, 32), 'crop': True, - 'upscale': True}, - 'admin_sidebar_preview': {'size': (SIDEBAR_IMAGE_WIDTH, 10000)}, - 'admin_directory_listing_icon': {'size': (48, 48), - 'crop': True, 'upscale': True}, - 'admin_tiny_icon': {'size': (32, 32), 'crop': True, 'upscale': True}, - } - file_type = 'Image' - _icon = "image" - - _height = models.IntegerField(null=True, blank=True) - _width = models.IntegerField(null=True, blank=True) - date_taken = models.DateTimeField(_('date taken'), null=True, blank=True, - editable=False) +from django.conf import settings +from django.core.exceptions import ValidationError +from django.db import models +from django.utils.timezone import get_current_timezone, make_aware, now +from django.utils.translation import gettext_lazy as _ - default_alt_text = models.CharField(_('default alt text'), max_length=255, blank=True, null=True) - default_caption = models.CharField(_('default caption'), max_length=255, blank=True, null=True) +from .abstract import BaseImage - author = models.CharField(_('author'), max_length=255, null=True, blank=True) - must_always_publish_author_credit = models.BooleanField(_('must always publish author credit'), default=False) - must_always_publish_copyright = models.BooleanField(_('must always publish copyright'), default=False) +logger = logging.getLogger("filer") - subject_location = models.CharField(_('subject location'), max_length=64, null=True, blank=True, - default=None) - @classmethod - def matches_file_type(cls, iname, ifile, request): - # This was originally in admin/clipboardadmin.py it was inside of a try - # except, I have moved it here outside of a try except because I can't - # figure out just what kind of exception this could generate... all it was - # doing for me was obscuring errors... - # --Dave Butler - iext = os.path.splitext(iname)[1].lower() - return iext in ['.jpg', '.jpeg', '.png', '.gif'] +# This is the standard Image model which can be swapped for a custom model using FILER_IMAGE_MODEL setting +class Image(BaseImage): + date_taken = models.DateTimeField( + _("date taken"), + null=True, + blank=True, + editable=False, + ) + + author = models.CharField( + _("author"), + max_length=255, + null=True, + blank=True, + ) + + default_credit = models.CharField( + _('default credit text'), max_length=255, blank=True, null=True, + help_text=_('Credit text gives credit to the owner or licensor of ' + 'an image; it is displayed below the image plugin, or ' + 'below the caption text on an image plugin, if that ' + 'option is selected; it is displayed along the bottom ' + 'of an image in the photo gallery plugin; there is a ' + '30-character limit, including spaces.')) + + must_always_publish_author_credit = models.BooleanField( + _("must always publish author credit"), + default=False, + ) + + must_always_publish_copyright = models.BooleanField( + _('must always publish copyright'), + default=False, + ) + + class Meta(BaseImage.Meta): + swappable = 'FILER_IMAGE_MODEL' + default_manager_name = 'objects' + + def clean(self): + if self.default_credit: + self.default_credit = self.default_credit.strip() + if self.default_alt_text: + self.default_alt_text = self.default_alt_text.strip() + if self.default_caption: + self.default_caption = self.default_caption.strip() + + if int(len(self.default_credit or '')) > 30: + raise ValidationError( + "Ensure default credit text has at most 30 characters (" + "%s characters found)." % len(self.default_credit)) + super().clean() def save(self, *args, **kwargs): if self.date_taken is None: try: exif_date = self.exif.get('DateTimeOriginal', None) if exif_date is not None: - d, t = str.split(exif_date.values) + d, t = exif_date.split(" ") year, month, day = d.split(':') hour, minute, second = t.split(':') - self.date_taken = datetime( - int(year), int(month), int(day), - int(hour), int(minute), int(second)) - except: + if getattr(settings, "USE_TZ", False): + tz = get_current_timezone() + self.date_taken = make_aware(datetime( + int(year), int(month), int(day), + int(hour), int(minute), int(second)), tz) + else: + self.date_taken = datetime( + int(year), int(month), int(day), + int(hour), int(minute), int(second)) + except Exception: pass if self.date_taken is None: - self.date_taken = datetime.now() - self.has_all_mandatory_data = self._check_validity() - try: - # do this more efficient somehow? - self.file.seek(0) - self._width, self._height = PILImage.open(self.file).size - except Exception: - # probably the image is missing. nevermind. - pass - super(Image, self).save(*args, **kwargs) - - def _check_validity(self): - if not self.name: - return False - return True - - def sidebar_image_ratio(self): - if self.width: - return float(self.width) / float(self.SIDEBAR_IMAGE_WIDTH) - else: - return 1.0 - - def _get_exif(self): - if hasattr(self, '_exif_cache'): - return self._exif_cache - else: - if self.file: - self._exif_cache = get_exif_for_file(self.file.path) - else: - self._exif_cache = {} - return self._exif_cache - exif = property(_get_exif) - - def has_edit_permission(self, request): - return self.has_generic_permission(request, 'edit') - - def has_read_permission(self, request): - return self.has_generic_permission(request, 'read') - - def has_add_children_permission(self, request): - return self.has_generic_permission(request, 'add_children') - - def has_generic_permission(self, request, permission_type): - """ - Return true if the current user has permission on this - image. Return the string 'ALL' if the user has all rights. - """ - user = request.user - if not user.is_authenticated() or not user.is_staff: - return False - elif user.is_superuser: - return True - elif user == self.owner: - return True - elif self.folder: - return self.folder.has_generic_permission(request, permission_type) - else: - return False - - @property - def label(self): - if self.name in ['', None]: - return self.original_filename or 'unnamed file' - else: - return self.name - - @property - def width(self): - return self._width or 0 - - @property - def height(self): - return self._height or 0 - - @property - def icons(self): - _icons = {} - for size in filer_settings.FILER_ADMIN_ICON_SIZES: - try: - thumbnail_options = { - 'size': (int(size), int(size)), - 'crop': True, - 'upscale': True, - 'subject_location': self.subject_location} - thumb = self.file.get_thumbnail(thumbnail_options) - _icons[size] = thumb.url - except Exception, e: - # catch exception and manage it. We can re-raise it for debugging - # purposes and/or just logging it, provided user configured - # proper logging configuration - if filer_settings.FILER_ENABLE_LOGGING: - logger.error('Error while generating icons: %s',e) - if filer_settings.FILER_DEBUG: - raise e - return _icons - - @property - def thumbnails(self): - _thumbnails = {} - for name, opts in Image.DEFAULT_THUMBNAILS.items(): - try: - opts.update({'subject_location': self.subject_location}) - thumb = self.file.get_thumbnail(opts) - _thumbnails[name] = thumb.url - except Exception,e: - # catch exception and manage it. We can re-raise it for debugging - # purposes and/or just logging it, provided user configured - # proper logging configuration - if filer_settings.FILER_ENABLE_LOGGING: - logger.error('Error while generating thumbnail: %s',e) - if filer_settings.FILER_DEBUG: - raise e - return _thumbnails - - @property - def easy_thumbnails_thumbnailer(self): - tn = FilerThumbnailer( - file=self.file.file, name=self.file.name, - source_storage=self.file.source_storage, - thumbnail_storage=self.file.thumbnail_storage, - thumbnail_basedir=self.file.thumbnail_basedir) - return tn - - class Meta: - app_label = 'filer' - verbose_name = _('image') - verbose_name_plural = _('images') + self.date_taken = now() + super().save(*args, **kwargs) diff --git a/filer/models/mixins.py b/filer/models/mixins.py index 70c9a2eff..1d4cb2ce7 100644 --- a/filer/models/mixins.py +++ b/filer/models/mixins.py @@ -1,8 +1,13 @@ -#-*- coding: utf-8 -*- -from filer.settings import FILER_ADMIN_ICON_SIZES, FILER_STATICMEDIA_PREFIX +import warnings +from django.db import models +from django.templatetags.static import static +from django.utils.translation import gettext_lazy as _ -class IconsMixin(object): +from ..settings import FILER_ADMIN_ICON_SIZES + + +class IconsMixin: """ Can be used on any model that has a _icon attribute. will return a dict containing urls for icons of different sizes with that name. @@ -12,6 +17,42 @@ def icons(self): r = {} if getattr(self, '_icon', False): for size in FILER_ADMIN_ICON_SIZES: - r[size] = "%sicons/%s_%sx%s.png" % ( - FILER_STATICMEDIA_PREFIX, self._icon, size, size) + try: + r[size] = static("filer/icons/{}_{}x{}.png".format( + self._icon, size, size)) + except ValueError: + pass return r + + +# PBS-specific: trashable decorator +def trashable(cls): + + deleted_at = models.DateTimeField( + _('deleted at'), editable=False, blank=True, null=True) + + for custom_method in ['soft_delete', 'hard_delete', 'restore']: + if not hasattr(cls, custom_method): + raise NotImplementedError("Method %s required." % custom_method) + + def is_in_trash(instance): + return instance.deleted_at is not None + + # custom delete method + def delete_restorable(instance, *args, **kwargs): + to_trash = kwargs.pop('to_trash', True) + if not instance.deleted_at and to_trash: + instance.soft_delete(*args, **kwargs) + else: + instance.hard_delete(*args, **kwargs) + + # override delete method + def delete(instance, *args, **kwargs): + delete_restorable(instance, *args, **kwargs) + delete.alters_data = True + + cls.add_to_class('is_in_trash', is_in_trash) + cls.add_to_class('delete_restorable', delete_restorable) + cls.add_to_class('delete', delete) + cls.add_to_class('deleted_at', deleted_at) + return cls diff --git a/filer/models/thumbnailoptionmodels.py b/filer/models/thumbnailoptionmodels.py new file mode 100644 index 000000000..883df7989 --- /dev/null +++ b/filer/models/thumbnailoptionmodels.py @@ -0,0 +1,61 @@ +from django.db import models +from django.utils.translation import gettext_lazy as _ + + +class ThumbnailOption(models.Model): + """ + This class defines the option use to create the thumbnail. + """ + name = models.CharField( + _("name"), + max_length=100, + ) + + width = models.IntegerField( + _("width"), + help_text=_("width in pixel."), + ) + + height = models.IntegerField( + _("height"), + help_text=_("height in pixel."), + ) + + crop = models.BooleanField( + _("crop"), + default=True, + ) + + upscale = models.BooleanField( + _("upscale"), + default=True, + ) + + class Meta: + app_label = 'filer' + ordering = ('width', 'height') + verbose_name = _("thumbnail option") + verbose_name_plural = _("thumbnail options") + + def __str__(self): + return f'{self.name} -- {self.width} x {self.height}' + + @property + def as_dict(self): + """ + This property returns a dictionary suitable for Thumbnailer.get_thumbnail() + + Sample code: + # thumboption_obj is a ThumbnailOption instance + # filerimage is a Image instance + option_dict = thumboption_obj.as_dict + thumbnailer = filerimage.easy_thumbnails_thumbnailer + thumb_image = thumbnailer.get_thumbnail(option_dict) + """ + return { + 'size': (self.width, self.height), + 'width': self.width, + 'height': self.height, + 'crop': self.crop, + 'upscale': self.upscale, + } diff --git a/filer/models/tools.py b/filer/models/tools.py index b12e25feb..b7e607738 100644 --- a/filer/models/tools.py +++ b/filer/models/tools.py @@ -1,10 +1,16 @@ #-*- coding: utf-8 -*- +from django.contrib import messages +from django.utils.translation import gettext as _ + from filer.models import Clipboard def discard_clipboard(clipboard): clipboard.files.clear() +def discard_clipboard_files(clipboard, files): + clipboard.clipboarditem_set.filter(file__in=files).delete() + def delete_clipboard(clipboard): for file_obj in clipboard.files.all(): @@ -12,14 +18,22 @@ def delete_clipboard(clipboard): def get_user_clipboard(user): - if user.is_authenticated(): + if user.is_authenticated: clipboard = Clipboard.objects.get_or_create(user=user)[0] return clipboard -def move_file_to_clipboard(files, clipboard): +def move_file_to_clipboard(request, files, clipboard): count = 0 + file_names = [f.clean_actual_name for f in files] + already_existing = [ + f.clean_actual_name + for f in clipboard.files.all() if f.clean_actual_name in file_names] for file_obj in files: + if file_obj.clean_actual_name in already_existing: + messages.error(request, _('Clipboard already contains a file ' + 'named %s') % file_obj.clean_actual_name) + continue if clipboard.append_file(file_obj): file_obj.folder = None file_obj.save() @@ -27,12 +41,35 @@ def move_file_to_clipboard(files, clipboard): return count -def move_files_from_clipboard_to_folder(clipboard, folder): - return move_files_to_folder(clipboard.files.all(), folder) +def move_files_from_clipboard_to_folder(request, clipboard, folder): + return move_files_to_folder(request, clipboard.files.all(), folder) -def move_files_to_folder(files, folder): +def split_files_valid_for_destination(files, destination): + file_names = [f.clean_actual_name for f in files] + already_existing = [ + f.clean_actual_name + for f in destination.entries_with_names(file_names)] + + valid_files, invalid_files = [], [] for file_obj in files: - file_obj.folder = folder + if file_obj.clean_actual_name in already_existing: + invalid_files.append(file_obj) + else: + valid_files.append(file_obj) + return valid_files, invalid_files + + +def move_files_to_folder(request, files, destination): + valid_files, invalid_files = split_files_valid_for_destination( + files, destination) + + for file_obj in valid_files: + file_obj.folder = destination file_obj.save() - return True + + for file_obj in invalid_files: + messages.error( + request, _("File or folder named %s already exists in " + "this folder.") % file_obj.clean_actual_name) + return valid_files diff --git a/filer/models/virtualitems.py b/filer/models/virtualitems.py index dc22aaeac..44fccc9bb 100644 --- a/filer/models/virtualitems.py +++ b/filer/models/virtualitems.py @@ -1,9 +1,11 @@ -#-*- coding: utf-8 -*- -from django.core import urlresolvers -from django.utils.translation import ugettext_lazy as _ -from filer.models import mixins -from filer.models.filemodels import File -from filer.models.foldermodels import Folder +from django.urls import reverse +from django.utils.translation import gettext_lazy as _ + +from .. import settings as filer_settings +from ..utils.cms_roles import has_admin_role +from . import mixins +from .filemodels import File +from .foldermodels import Folder class DummyFolder(mixins.IconsMixin): @@ -13,6 +15,8 @@ class DummyFolder(mixins.IconsMixin): is_smart_folder = True can_have_subfolders = False parent = None + pk = None + id = None _icon = "plainfolder" @property @@ -42,17 +46,27 @@ def logical_path(self): class UnfiledImages(DummyFolder): + """PBS name for unsorted/unfiled images.""" name = _("unfiled files") is_root = True + is_unsorted_uploads = True _icon = "unfiled_folder" + def __init__(self, user=None): + super().__init__() + self.user = user + def _files(self): - return File.objects.filter(folder__isnull=True) + return File.objects.filter( + folder__isnull=True, clipboarditem__isnull=True) files = property(_files) def get_admin_directory_listing_url_path(self): - return urlresolvers.reverse( - 'admin:filer-directory_listing-unfiled_images') + return reverse('admin:filer-directory_listing-unfiled_images') + + +# Upstream compat alias +UnsortedImages = UnfiledImages class ImagesWithMissingData(DummyFolder): @@ -65,8 +79,7 @@ def files(self): return File.objects.filter(has_all_mandatory_data=False) def get_admin_directory_listing_url_path(self): - return urlresolvers.reverse( - 'admin:filer-directory_listing-images_with_missing_data') + return reverse('admin:filer-directory_listing-images_with_missing_data') class FolderRoot(DummyFolder): @@ -74,6 +87,7 @@ class FolderRoot(DummyFolder): is_root = True is_smart_folder = False can_have_subfolders = True + restricted = False @property def virtual_folders(self): @@ -91,5 +105,18 @@ def contains_folder(self, folder_name): except Folder.DoesNotExist: return False + def entries_with_names(self, names): + return self.children.filter(name__in=names) + def get_admin_directory_listing_url_path(self): - return urlresolvers.reverse('admin:filer-directory_listing-root') + return reverse('admin:filer-directory_listing-root') + + # PBS-specific permission methods + def is_restricted_for_user(self, user): + return not has_admin_role(user) + + def can_change_restricted(self, user): + return has_admin_role(user) + + def is_readonly_for_user(self, user): + return not has_admin_role(user) diff --git a/filer/server/backends/base.py b/filer/server/backends/base.py index d7e8d1377..5e811ee4e 100644 --- a/filer/server/backends/base.py +++ b/filer/server/backends/base.py @@ -1,18 +1,14 @@ -#-*- coding: utf-8 -*- -from django.utils.encoding import smart_str -import mimetypes import os +from django.utils.encoding import smart_str + -class ServerBase(object): +class ServerBase: """ Server classes define a way to serve a Django File object. Warning: this API is EXPERIMENTAL and may change at any time. """ - def get_mimetype(self, path): - return mimetypes.guess_type(path)[0] or 'application/octet-stream' - def default_headers(self, **kwargs): self.save_as_header(**kwargs) self.size_header(**kwargs) @@ -21,24 +17,29 @@ def save_as_header(self, response, **kwargs): """ * if save_as is False the header will not be added * if save_as is a filename, it will be used in the header - * if save_as is None the filename will be determined from the file path + * if save_as is True or None the filename will be determined from the + file path """ save_as = kwargs.get('save_as', None) - if save_as == False: + if save_as is False: return file_obj = kwargs.get('file_obj', None) - filename = None - if save_as: - filename = save_as - else: + if save_as is True or save_as is None: filename = os.path.basename(file_obj.path) - response['Content-Disposition'] = smart_str(u'attachment; filename=%s' % filename) + else: + filename = save_as + response['Content-Disposition'] = smart_str( + 'attachment; filename=%s' % filename) def size_header(self, response, **kwargs): size = kwargs.get('size', None) - #file = kwargs.get('file', None) + # file = kwargs.get('file', None) if size: response['Content-Length'] = size - # we should not do this, because it accesses the file. and that might be an expensive operation. + # we should not do this, because it accesses the file. and that might + # be an expensive operation. # elif file and file.size is not None: # response['Content-Length'] = file.size + + def serve(self, request, filer_file, **kwargs): + raise NotImplementedError(".serve() must be overridden") diff --git a/filer/server/backends/default.py b/filer/server/backends/default.py index c7a63c411..736061a75 100644 --- a/filer/server/backends/default.py +++ b/filer/server/backends/default.py @@ -1,10 +1,12 @@ -#-*- coding: utf-8 -*- +import mimetypes import os import stat + from django.http import Http404, HttpResponse, HttpResponseNotModified from django.utils.http import http_date from django.views.static import was_modified_since -from filer.server.backends.base import ServerBase + +from .base import ServerBase class DefaultServer(ServerBase): @@ -14,19 +16,22 @@ class DefaultServer(ServerBase): This will only work for files that can be accessed in the local filesystem. """ - def serve(self, request, file_obj, **kwargs): - fullpath = file_obj.path + def serve(self, request, filer_file, **kwargs): + fullpath = filer_file.path # the following code is largely borrowed from `django.views.static.serve` # and django-filetransfers: filetransfers.backends.default if not os.path.exists(fullpath): raise Http404('"%s" does not exist' % fullpath) # Respect the If-Modified-Since header. statobj = os.stat(fullpath) - mimetype = self.get_mimetype(fullpath) + mime_type = getattr(filer_file, 'mime_type', None) + if mime_type is None: + mime_type = mimetypes.guess_type(fullpath)[0] or 'application/octet-stream' + response_params = {'content_type': mime_type} if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'), - statobj[stat.ST_MTIME], statobj[stat.ST_SIZE]): - return HttpResponseNotModified(mimetype=mimetype) - response = HttpResponse(open(fullpath, 'rb').read(), mimetype=mimetype) + statobj[stat.ST_MTIME]): + return HttpResponseNotModified(**response_params) + response = HttpResponse(open(fullpath, 'rb').read(), **response_params) response["Last-Modified"] = http_date(statobj[stat.ST_MTIME]) - self.default_headers(request=request, response=response, file_obj=file_obj, **kwargs) + self.default_headers(request=request, response=response, file_obj=filer_file, **kwargs) return response diff --git a/filer/server/backends/nginx.py b/filer/server/backends/nginx.py index 639843877..73e222b20 100644 --- a/filer/server/backends/nginx.py +++ b/filer/server/backends/nginx.py @@ -1,6 +1,8 @@ -#-*- coding: utf-8 -*- +import mimetypes + from django.http import HttpResponse -from filer.server.backends.base import ServerBase + +from .base import ServerBase class NginxXAccelRedirectServer(ServerBase): @@ -18,11 +20,13 @@ def __init__(self, location, nginx_location): def get_nginx_location(self, path): return path.replace(self.location, self.nginx_location) - def serve(self, request, file_obj, **kwargs): - # we should not use get_mimetype() here, because it tries to access the file in the filesystem. - #response = HttpResponse(mimetype=self.get_mimetype(file.path)) + def serve(self, request, filer_file, **kwargs): response = HttpResponse() - nginx_path = self.get_nginx_location(file_obj.path) + mime_type = getattr(filer_file, 'mime_type', None) + if mime_type is None: + mime_type = mimetypes.guess_type(filer_file.path)[0] or 'application/octet-stream' + response['Content-Type'] = mime_type + nginx_path = self.get_nginx_location(filer_file.path) response['X-Accel-Redirect'] = nginx_path - self.default_headers(request=request, response=response, file_obj=file_obj, **kwargs) + self.default_headers(request=request, response=response, file_obj=filer_file, **kwargs) return response diff --git a/filer/server/backends/xsendfile.py b/filer/server/backends/xsendfile.py index cd3316f64..27d73654f 100644 --- a/filer/server/backends/xsendfile.py +++ b/filer/server/backends/xsendfile.py @@ -1,17 +1,20 @@ -#-*- coding: utf-8 -*- +import mimetypes + from django.http import HttpResponse -from filer.server.backends.base import ServerBase + +from .base import ServerBase class ApacheXSendfileServer(ServerBase): - def serve(self, request, file_obj, **kwargs): + def serve(self, request, filer_file, **kwargs): response = HttpResponse() - response['X-Sendfile'] = file_obj.path + response['X-Sendfile'] = filer_file.path # This is needed for lighttpd, hopefully this will # not be needed after this is fixed: # http://redmine.lighttpd.net/issues/2076 - response['Content-Type'] = self.get_mimetype(file_obj.path) + response['Content-Type'] = getattr(filer_file, 'mime_type', None) or \ + mimetypes.guess_type(filer_file.path)[0] or 'application/octet-stream' - self.default_headers(request=request, response=response, file_obj=file_obj, **kwargs) + self.default_headers(request=request, response=response, file_obj=filer_file, **kwargs) return response diff --git a/filer/server/main_server_urls.py b/filer/server/main_server_urls.py index 01d8925c4..232c1fe2a 100644 --- a/filer/server/main_server_urls.py +++ b/filer/server/main_server_urls.py @@ -1,6 +1,8 @@ -#-*- coding: utf-8 -*- -from django.conf.urls.defaults import patterns, url +from django.urls import re_path -urlpatterns = patterns('filer.server.views', - url(r'^(?P.*)$', 'serve_protected_file',), -) +from . import views + + +urlpatterns = [ + re_path(r'^(?P.*)$', views.serve_protected_file), +] diff --git a/filer/server/thumbnails_server_urls.py b/filer/server/thumbnails_server_urls.py index 26d3f6843..7d2cb0395 100644 --- a/filer/server/thumbnails_server_urls.py +++ b/filer/server/thumbnails_server_urls.py @@ -1,6 +1,8 @@ -#-*- coding: utf-8 -*- -from django.conf.urls.defaults import patterns, url +from django.urls import re_path -urlpatterns = patterns('filer.server.views', - url(r'^(?P.*)$', 'serve_protected_thumbnail',), -) +from . import views + + +urlpatterns = [ + re_path(r'^(?P.*)$', views.serve_protected_thumbnail), +] diff --git a/filer/server/urls.py b/filer/server/urls.py index 5f1519b73..8f758dcc9 100644 --- a/filer/server/urls.py +++ b/filer/server/urls.py @@ -1,11 +1,12 @@ -#-*- coding: utf-8 -*- -from django.conf.urls.defaults import patterns, url, include -from filer import settings as filer_settings +from django.urls import include, re_path + +from .. import settings as filer_settings + if not filer_settings.FILER_0_8_COMPATIBILITY_MODE: - urlpatterns = patterns('filer.server.views', - url(r'^' + filer_settings.FILER_PRIVATEMEDIA_STORAGE.base_url.lstrip('/'), include('filer.server.main_server_urls')), - url(r'^' + filer_settings.FILER_PRIVATEMEDIA_THUMBNAIL_STORAGE.base_url.lstrip('/'), include('filer.server.thumbnails_server_urls')), - ) + urlpatterns = [ + re_path(r'^' + filer_settings.FILER_PRIVATEMEDIA_STORAGE.base_url.lstrip('/'), include('filer.server.main_server_urls')), + re_path(r'^' + filer_settings.FILER_PRIVATEMEDIA_THUMBNAIL_STORAGE.base_url.lstrip('/'), include('filer.server.thumbnails_server_urls')), + ] else: - urlpatterns = patterns('') \ No newline at end of file + urlpatterns = [] diff --git a/filer/server/views.py b/filer/server/views.py index dcd6b87e7..90b394abb 100644 --- a/filer/server/views.py +++ b/filer/server/views.py @@ -1,16 +1,20 @@ -#-*- coding: utf-8 -*- from django.conf import settings from django.core.exceptions import PermissionDenied from django.http import Http404 +from django.views.decorators.cache import never_cache + from easy_thumbnails.files import ThumbnailFile -from filer import settings as filer_settings -from filer.models import File -from filer.utils.filer_easy_thumbnails import thumbnail_to_original_filename + +from .. import settings as filer_settings +from ..models import File +from ..utils.filer_easy_thumbnails import thumbnail_to_original_filename + server = filer_settings.FILER_PRIVATEMEDIA_SERVER thumbnail_server = filer_settings.FILER_PRIVATEMEDIA_THUMBNAIL_SERVER +@never_cache def serve_protected_file(request, path): """ Serve protected files to authenticated users with read permissions. @@ -24,9 +28,10 @@ def serve_protected_file(request, path): raise PermissionDenied else: raise Http404('File not found') - return server.serve(request, file_obj=file_obj.file, save_as=False) + return server.serve(request, file_obj, save_as=False) +@never_cache def serve_protected_thumbnail(request, path): """ Serve protected thumbnails to authenticated users. @@ -46,6 +51,7 @@ def serve_protected_thumbnail(request, path): raise Http404('File not found') try: thumbnail = ThumbnailFile(name=path, storage=file_obj.file.thumbnail_storage) + thumbnail.mime_type = file_obj.mime_type return thumbnail_server.serve(request, thumbnail, save_as=False) except Exception: raise Http404('File not found') diff --git a/filer/settings.py b/filer/settings.py index c0597abb5..7d2c96520 100644 --- a/filer/settings.py +++ b/filer/settings.py @@ -1,68 +1,112 @@ -#-*- coding: utf-8 -*- -from django.conf import settings -from django.core.files.storage import get_storage_class -from filer.utils.loader import load_object -from filer.utils.recursive_dictionary import RecursiveDictionaryWithExcludes +import logging import os +from django.conf import settings +from django.utils.module_loading import import_string as get_storage_class +from django.utils.translation import gettext_lazy as _ + +from .utils.loader import load_object +from .utils.recursive_dictionary import RecursiveDictionaryWithExcludes + -FILER_DEBUG = getattr(settings, 'FILER_DEBUG', False) # When True makes +logger = logging.getLogger(__name__) + +# FILER_IMAGE_MODEL setting is used to swap Image model. +# If such global setting does not exist, it will be created at this point (with default model name). +# This is needed especially when using this setting in migrations. +if not hasattr(settings, 'FILER_IMAGE_MODEL'): + setattr(settings, 'FILER_IMAGE_MODEL', 'filer.Image') +FILER_IMAGE_MODEL = settings.FILER_IMAGE_MODEL + +FILER_DEBUG = getattr(settings, 'FILER_DEBUG', False) # When True makes FILER_SUBJECT_LOCATION_IMAGE_DEBUG = getattr(settings, 'FILER_SUBJECT_LOCATION_IMAGE_DEBUG', False) +FILER_WHITESPACE_COLOR = getattr(settings, 'FILER_WHITESPACE_COLOR', '#FFFFFF') FILER_0_8_COMPATIBILITY_MODE = getattr(settings, 'FILER_0_8_COMPATIBILITY_MODE', False) FILER_ENABLE_LOGGING = getattr(settings, 'FILER_ENABLE_LOGGING', False) if FILER_ENABLE_LOGGING: - FILER_ENABLE_LOGGING = (FILER_ENABLE_LOGGING and (getattr(settings,'LOGGING') and - ('' in settings.LOGGING['loggers'] or - 'filer' in settings.LOGGING['loggers']))) + FILER_ENABLE_LOGGING = ( + FILER_ENABLE_LOGGING and (getattr(settings, 'LOGGING') + and ('' in settings.LOGGING['loggers'] + or 'filer' in settings.LOGGING['loggers']))) + +# PBS-specific: nohash rootfolders +FILER_NOHASH_ROOTFOLDERS = getattr(settings, 'FILER_NOHASH_ROOTFOLDERS', []) FILER_ENABLE_PERMISSIONS = getattr(settings, 'FILER_ENABLE_PERMISSIONS', False) FILER_ALLOW_REGULAR_USERS_TO_ADD_ROOT_FOLDERS = getattr(settings, 'FILER_ALLOW_REGULAR_USERS_TO_ADD_ROOT_FOLDERS', False) FILER_IS_PUBLIC_DEFAULT = getattr(settings, 'FILER_IS_PUBLIC_DEFAULT', True) -FILER_PAGINATE_BY = getattr(settings, 'FILER_PAGINATE_BY', 20) +FILER_PAGINATE_BY = getattr(settings, 'FILER_PAGINATE_BY', 100) + +if hasattr(settings, "FILER_ADMIN_ICON_SIZES"): + logger.warning("FILER_ADMIN_ICON_SIZES is deprecated and will be removed in the future.") + +_ICON_SIZES = getattr(settings, 'FILER_ADMIN_ICON_SIZES', ('16', '32', '48', '64')) +# Reliably sort by integer value, but keep icon size as string. +FILER_ADMIN_ICON_SIZES = [str(i) for i in sorted([int(s) for s in _ICON_SIZES])] + +# PBS legacy compat FILER_STATICMEDIA_PREFIX = getattr(settings, 'FILER_STATICMEDIA_PREFIX', None) if not FILER_STATICMEDIA_PREFIX: FILER_STATICMEDIA_PREFIX = (getattr(settings, 'STATIC_URL', None) or settings.MEDIA_URL) + 'filer/' -FILER_ADMIN_ICON_SIZES = getattr(settings,"FILER_ADMIN_ICON_SIZES",( - '16', '32', '48', '64', - )) +# Currently, these two icon sizes are hard-coded into the admin and admin templates +FILER_TABLE_ICON_SIZE = getattr(settings, "FILER_TABLE_ICON_SIZE", 40) +FILER_THUMBNAIL_ICON_SIZE = getattr(settings, "FILER_THUMBNAIL_ICON_SIZE", 120) +DEFERRED_THUMBNAIL_SIZES = ( + FILER_TABLE_ICON_SIZE, + 2 * FILER_TABLE_ICON_SIZE, + FILER_THUMBNAIL_ICON_SIZE, + 2 * FILER_THUMBNAIL_ICON_SIZE, +) + # This is an ordered iterable that describes a list of # classes that I should check for when adding files -FILER_FILE_MODELS = getattr(settings, 'FILER_FILE_MODELS', - ( - 'filer.models.imagemodels.Image', - 'filer.models.filemodels.File', - ) -) +FILER_FILE_MODELS = getattr( + settings, 'FILER_FILE_MODELS', + (FILER_IMAGE_MODEL, 'filer.Archive', 'filer.File')) + +_FALLBACK_STORAGE_BACKEND = 'django.core.files.storage.FileSystemStorage' -DEFAULT_FILE_STORAGE = getattr(settings, 'DEFAULT_FILE_STORAGE', 'django.core.files.storage.FileSystemStorage') +if hasattr(settings, "STORAGES") and 'default' in settings.STORAGES: + DEFAULT_FILE_STORAGE = settings.STORAGES['default'].get('BACKEND', _FALLBACK_STORAGE_BACKEND) +else: + DEFAULT_FILE_STORAGE = getattr(settings, 'DEFAULT_FILE_STORAGE', _FALLBACK_STORAGE_BACKEND) + # PBS: Django 5.1+ removed the legacy DEFAULT_FILE_STORAGE setting and relies + # exclusively on STORAGES['default']. If the host project (e.g. bento) + # defines STORAGES without a 'default' key, Django's internal + # default_storage lookup will raise InvalidStorageError. Inject the + # entry so the rest of the framework keeps working. + if hasattr(settings, "STORAGES"): + settings.STORAGES['default'] = { + 'BACKEND': DEFAULT_FILE_STORAGE, + } MINIMAL_FILER_STORAGES = { 'public': { 'main': { 'ENGINE': None, 'OPTIONS': {}, - }, + }, 'thumbnails': { 'ENGINE': None, 'OPTIONS': {}, - } + } }, 'private': { 'main': { 'ENGINE': None, 'OPTIONS': {}, - }, + }, 'thumbnails': { 'ENGINE': None, 'OPTIONS': {}, - }, }, - } + }, +} DEFAULT_FILER_STORAGES = { @@ -165,20 +209,22 @@ FILER_STORAGES.rec_update(user_filer_storages) + def update_storage_settings(user_settings, defaults, s, t): if not user_settings[s][t]['ENGINE']: user_settings[s][t]['ENGINE'] = defaults[s][t]['ENGINE'] user_settings[s][t]['OPTIONS'] = defaults[s][t]['OPTIONS'] if t == 'main': - if not 'UPLOAD_TO' in user_settings[s][t]: + if 'UPLOAD_TO' not in user_settings[s][t]: user_settings[s][t]['UPLOAD_TO'] = defaults[s][t]['UPLOAD_TO'] - if not 'UPLOAD_TO_PREFIX' in user_settings[s][t]: + if 'UPLOAD_TO_PREFIX' not in user_settings[s][t]: user_settings[s][t]['UPLOAD_TO_PREFIX'] = defaults[s][t]['UPLOAD_TO_PREFIX'] if t == 'thumbnails': - if not 'THUMBNAIL_OPTIONS' in user_settings[s][t]: + if 'THUMBNAIL_OPTIONS' not in user_settings[s][t]: user_settings[s][t]['THUMBNAIL_OPTIONS'] = defaults[s][t]['THUMBNAIL_OPTIONS'] return user_settings + update_storage_settings(FILER_STORAGES, DEFAULT_FILER_STORAGES, 'public', 'main') update_storage_settings(FILER_STORAGES, DEFAULT_FILER_STORAGES, 'public', 'thumbnails') update_storage_settings(FILER_STORAGES, DEFAULT_FILER_STORAGES, 'private', 'main') @@ -187,17 +233,18 @@ def update_storage_settings(user_settings, defaults, s, t): FILER_SERVERS = RecursiveDictionaryWithExcludes(MINIMAL_FILER_SERVERS, rec_excluded_keys=('OPTIONS',)) FILER_SERVERS.rec_update(getattr(settings, 'FILER_SERVERS', {})) + def update_server_settings(settings, defaults, s, t): if not settings[s][t]['ENGINE']: settings[s][t]['ENGINE'] = defaults[s][t]['ENGINE'] settings[s][t]['OPTIONS'] = defaults[s][t]['OPTIONS'] return settings + update_server_settings(FILER_SERVERS, DEFAULT_FILER_SERVERS, 'private', 'main') update_server_settings(FILER_SERVERS, DEFAULT_FILER_SERVERS, 'private', 'thumbnails') - # Public media (media accessible without any permission checks) FILER_PUBLICMEDIA_STORAGE = get_storage_class(FILER_STORAGES['public']['main']['ENGINE'])(**FILER_STORAGES['public']['main']['OPTIONS']) FILER_PUBLICMEDIA_UPLOAD_TO = load_object(FILER_STORAGES['public']['main']['UPLOAD_TO']) @@ -216,3 +263,108 @@ def update_server_settings(settings, defaults, s, t): FILER_PRIVATEMEDIA_THUMBNAIL_OPTIONS = FILER_STORAGES['private']['thumbnails']['THUMBNAIL_OPTIONS'] FILER_PRIVATEMEDIA_SERVER = load_object(FILER_SERVERS['private']['main']['ENGINE'])(**FILER_SERVERS['private']['main']['OPTIONS']) FILER_PRIVATEMEDIA_THUMBNAIL_SERVER = load_object(FILER_SERVERS['private']['thumbnails']['ENGINE'])(**FILER_SERVERS['private']['thumbnails']['OPTIONS']) + +# By default limit number of simultaneous uploads if we are using SQLite +if settings.DATABASES['default']['ENGINE'].endswith('sqlite3'): + _uploader_connections = 1 +else: + _uploader_connections = 3 +FILER_UPLOADER_CONNECTIONS = getattr( + settings, 'FILER_UPLOADER_CONNECTIONS', _uploader_connections) +FILER_UPLOADER_MAX_FILES = getattr( + settings, 'FILER_UPLOADER_MAX_FILES', 100) +FILER_UPLOADER_MAX_FILE_SIZE = getattr( + settings, 'FILER_UPLOADER_MAX_FILE_SIZE', None) + + +FILER_DUMP_PAYLOAD = getattr(settings, 'FILER_DUMP_PAYLOAD', False) + +FILER_CANONICAL_URL = getattr(settings, 'FILER_CANONICAL_URL', 'canonical/') + +TABLE_LIST_TYPE = 'tb' +THUMBNAIL_LIST_TYPE = 'th' +FILER_FOLDER_ADMIN_LIST_TYPE_CHOICES = ( + TABLE_LIST_TYPE, + THUMBNAIL_LIST_TYPE, +) +FILER_FOLDER_ADMIN_DEFAULT_LIST_TYPE = getattr(settings, 'FILER_FOLDER_ADMIN_DEFAULT_LIST_TYPE', TABLE_LIST_TYPE) +if FILER_FOLDER_ADMIN_DEFAULT_LIST_TYPE not in FILER_FOLDER_ADMIN_LIST_TYPE_CHOICES: + FILER_FOLDER_ADMIN_DEFAULT_LIST_TYPE = TABLE_LIST_TYPE + +FILER_FOLDER_ADMIN_LIST_TYPE_SWITCHER_SETTINGS = { + TABLE_LIST_TYPE: { + 'icon': 'th-list', + 'tooltip_text': _('Show table view'), + 'template': 'admin/filer/folder/directory_table_list.html', + }, + THUMBNAIL_LIST_TYPE: { + 'icon': 'th-large', + 'tooltip_text': _('Show thumbnail view'), + 'template': 'admin/filer/folder/directory_thumbnail_list.html', + }, +} + +IMAGE_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.gif', '.webp'] +IMAGE_MIME_TYPES = ['gif', 'jpeg', 'png', 'x-png', 'svg+xml', 'webp'] + +FILE_VALIDATORS = { + "text/html": ["filer.validation.deny_html"], + "image/svg+xml": ["filer.validation.validate_svg"], + "application/octet-stream": ["filer.validation.deny"], +} + +remove_mime_types = getattr(settings, "FILER_REMOVE_FILE_VALIDATORS", []) +for mime_type in remove_mime_types: # pragma: no cover + if mime_type in FILE_VALIDATORS: + del FILE_VALIDATORS[mime_type] + +for mime_type, validators in getattr(settings, "FILER_ADD_FILE_VALIDATORS", {}).items(): # pragma: no cover + if mime_type in FILE_VALIDATORS: + FILE_VALIDATORS[mime_type] += list(validators) + else: + FILE_VALIDATORS[mime_type] = list(validators) + +FILER_MIME_TYPE_WHITELIST = getattr(settings, "FILER_MIME_TYPE_WHITELIST", []) + + +# Determine if django CMS is installed and if it comes with its own iconset +ICON_CSS_LIB = ("filer/css/admin_filer.fa.icons.css",) +if "cms" in settings.INSTALLED_APPS: # pragma: no cover + try: + from cms import __version__ + from cms.utils.urlutils import static_with_version + + if __version__ >= "4": + ICON_CSS_LIB = ( + static_with_version("cms/css/cms.admin.css"), + "filer/css/admin_filer.cms.icons.css", + ) + except (ModuleNotFoundError, ImportError): + pass + +# SVG are their own thumbnails if their size is below this limit +FILER_MAX_SVG_THUMBNAIL_SIZE = getattr(settings, "FILER_MAX_SVG_THUMBNAIL_SIZE", 1024 * 1024) # 1MB default + +# --- PBS-specific settings --- + +# PBS: folder structure affects the URL of files on storage +FOLDER_AFFECTS_URL = getattr(settings, 'FILER_FOLDER_AFFECTS_URL', False) + +# PBS: CDN settings +CDN_DOMAIN = getattr(settings, 'FILER_CDN_DOMAIN', None) +CDN_INVALIDATION_TIME = getattr(settings, 'FILER_CDN_INVALIDATION_TIME', 0) + +# PBS: Trash settings +FILER_TRASH_PREFIX = getattr(settings, 'FILER_TRASH_PREFIX', '_trash') +FILER_TRASH_CLEAN_INTERVAL = getattr(settings, 'FILER_TRASH_CLEAN_INTERVAL', 60 * 60 * 24) # defaults to one day + +# PBS: Roles Manager that controls how the filer checks permissions +_default_roles_manager = 'cmsroles.siteadmin.FilerRolesManager' +try: + import cmsroles # noqa: F401 +except ImportError: + _default_roles_manager = 'filer.utils.cms_roles.DefaultFilerRolesManager' + +FILER_ROLES_MANAGER = getattr(settings, + 'FILER_ROLES_MANAGER', + _default_roles_manager) diff --git a/filer/static/admin/libs/ace/css/ace.min.css b/filer/static/admin/libs/ace/css/ace.min.css new file mode 100644 index 000000000..8e14cdf2b --- /dev/null +++ b/filer/static/admin/libs/ace/css/ace.min.css @@ -0,0 +1,2 @@ +/* Ace theme v1.3.1 */ +html{min-height:100%;position:relative}body{background-color:#e4e6e9;min-height:100%;padding-bottom:0;font-family:'Open Sans';font-size:13px;color:#393939;line-height:1.5}.main-container:before{display:block;content:"";position:absolute;z-index:-2;width:100%;max-width:inherit;bottom:0;top:0;background-color:#FFF}.main-container.container,.rtl .main-container.container{padding-left:0;padding-right:0}.main-container.container:before{-webkit-box-shadow:0 0 0 1px rgba(0,0,0,.1);box-shadow:0 0 0 1px rgba(0,0,0,.1);width:inherit}@media (max-width:767px){.main-container.container:before{-webkit-box-shadow:none;box-shadow:none;width:100%}}.main-content{margin-left:0;min-height:100%;padding:0}.sidebar+.main-content{margin-left:190px}.page-content{background-color:#fff;position:relative;margin:0;padding:8px 20px 24px}.page-header{margin:0 0 12px;border-bottom:1px dotted #e2e2e2;padding-bottom:16px;padding-top:7px}.page-header h1{padding:0;margin:0 8px;font-size:24px;font-weight:lighter;color:#2679b5}.page-header h1 small{margin:0 6px;font-size:14px;font-weight:400;color:#8089a0}.ace-icon{text-align:center}a:active,a:focus{text-decoration:none}h1{font-size:32px;font-weight:400;font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif}h1.smaller{font-size:31px}h1.bigger{font-size:33px}h1.block{margin-bottom:16px}h2{font-size:26px;font-weight:400;font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif}h2.smaller{font-size:25px}h2.bigger{font-size:27px}h2.block{margin-bottom:16px}h3{font-size:22px;font-weight:400;font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif}h3.smaller{font-size:21px}h3.bigger{font-size:23px}h3.block{margin-bottom:16px}h4{font-size:18px;font-weight:400;font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif}h4.smaller{font-size:17px}h4.bigger{font-size:19px}h4.block{margin-bottom:16px}h5{font-size:15px;font-weight:400;font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif}h5.smaller{font-size:14px}h5.bigger{font-size:16px}h5.block{margin-bottom:16px}h6{font-size:13px;font-weight:400;font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif}h6.smaller{font-size:12px}h6.bigger{font-size:14px}h6.block{margin-bottom:16px}ol,ul{margin:0 0 10px 25px;padding:0}ol.margin-5,ul.margin-5{margin-left:5px}ol.margin-10,ul.margin-10{margin-left:10px}ol.margin-15,ul.margin-15{margin-left:15px}ol.margin-20,ul.margin-20{margin-left:20px}li>ol,li>ul{margin-left:18px}.list-inline,.list-unstyled{margin-left:0}.list-inline>li>.ace-icon:first-child,.list-unstyled>li>.ace-icon:first-child{width:18px;text-align:center}.spaced>li{margin-top:9px;margin-bottom:9px}.spaced2>li{margin-top:15px;margin-bottom:15px}li.divider{margin-top:3px;margin-bottom:3px;height:0;font-size:0}.spaced>li.divider{margin-top:5px;margin-bottom:5px}.spaced2>li.divider{margin-top:8px;margin-bottom:8px}li.divider:before{content:"";display:inline-block}.blockquote-reverse,blockquote,blockquote.pull-right{border-color:#e5eaf1}pre.prettyprint{white-space:pre-wrap}.modal-content{border-radius:0;-webkit-box-shadow:none;box-shadow:none}.modal-footer{padding-top:12px;padding-bottom:14px;border-top-color:#e4e9ee;-webkit-box-shadow:none;box-shadow:none;background-color:#eff3f8}.modal-header .close{font-size:32px}.well{border-radius:0}.well h1,.well h2,.well h3,.well h4,.well h5,.well h6{margin-top:0}.well h1,.well h2,.well h3{line-height:36px}.alert{font-size:14px;border-radius:0}.alert .close{font-size:16px}.alert-block p+p{margin-top:10px}.pager>li>span,.pagination>li>span{border-width:1px;border-radius:0!important}.pager>li>a,.pagination>li>a{border-width:1px;border-color:#d4dfe3;border-radius:0!important;color:#2283c5;background-color:#fafafa;margin:0 -1px 0 0;position:relative;z-index:auto}.pager>li>a:hover,.pagination>li>a:hover{color:#1c6ca2;background-color:#eaeff2;border-color:#c1d1d7;z-index:1}.pager>li>a:focus,.pagination>li>a:focus{background-color:#eaeef2}.pager>li.disabled>a,.pager>li.disabled>a:hover,.pagination>li.disabled>a,.pagination>li.disabled>a:hover{background-color:#f9f9f9;border-color:#d9d9d9;z-index:auto}.pagination>li.active>a,.pagination>li.active>a:hover{background-color:#6faed9;border-color:#6faed9;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25);z-index:2}.list-group-item{border-radius:0!important}.lighter{font-weight:lighter}.bolder{font-weight:bolder}.inline{display:inline-block!important}.block{display:block!important}.align-center,.center{text-align:center!important}.align-left{text-align:left!important}.align-right{text-align:right!important}.middle{vertical-align:middle}.align-middle{vertical-align:middle!important}.align-top{vertical-align:top!important}.align-bottom{vertical-align:bottom!important}.pos-rel,.position-relative{position:relative}.pos-abs,.position-absolute{position:absolute}.no-float{float:none!important}.line-height-normal{line-height:normal!important}.line-height-0{line-height:0!important}.line-height-1{line-height:1!important}.line-height-125{line-height:1.25!important}.line-height-150{line-height:1.5!important}.dark{color:#333!important}.white{color:#fff!important}.red{color:#dd5a43!important}.red2{color:#e08374!important}.light-red{color:#f77!important}.blue{color:#478fca!important}.light-blue{color:#93cbf9!important}.green{color:#69aa46!important}.light-green{color:#b0d877!important}.orange{color:#ff892a!important}.orange2{color:#feb902!important}.light-orange{color:#fcac6f!important}.purple{color:#a069c3!important}.pink{color:#c6699f!important}.pink2{color:#d6487e!important}.brown{color:brown!important}.grey{color:#777!important}.light-grey{color:#bbb!important}.bigger-110{font-size:110%!important}.bigger-120{font-size:120%!important}.bigger-130{font-size:130%!important}.bigger-140{font-size:140%!important}.bigger-150{font-size:150%!important}.bigger-160{font-size:160%!important}.bigger-170{font-size:170%!important}.bigger-180{font-size:180%!important}.bigger-190{font-size:190%!important}.bigger-200{font-size:200%!important}.bigger-210{font-size:210%!important}.bigger-220{font-size:220%!important}.bigger-230{font-size:230%!important}.bigger-240{font-size:240%!important}.bigger-250{font-size:250%!important}.bigger-260{font-size:260%!important}.bigger-270{font-size:270%!important}.bigger-280{font-size:280%!important}.bigger-290{font-size:290%!important}.bigger-300{font-size:300%!important}.bigger-115{font-size:115%!important}.bigger-125{font-size:125%!important}.bigger-175{font-size:175%!important}.bigger-225{font-size:225%!important}.bigger-275{font-size:275%!important}.smaller-90{font-size:90%!important}.smaller-80{font-size:80%!important}.smaller-70{font-size:70%!important}.smaller-60{font-size:60%!important}.smaller-50{font-size:50%!important}.smaller-40{font-size:40%!important}.smaller-30{font-size:30%!important}.smaller-20{font-size:20%!important}.smaller-75{font-size:75%!important}.width-20{width:20%!important}.width-30{width:30%!important}.width-35{width:35%!important}.width-40{width:40%!important}.width-45{width:45%!important}.width-50{width:50%!important}.width-55{width:55%!important}.width-60{width:60%!important}.width-65{width:65%!important}.width-70{width:70%!important}.width-80{width:80%!important}.width-85{width:85%!important}.width-90{width:90%!important}.width-95{width:95%!important}.width-100{width:100%!important}.width-75{width:75%!important}.width-25{width:25%!important}.width-auto{width:auto!important}.height-auto{height:auto!important}.no-padding{padding:0!important}.no-padding-bottom{padding-bottom:0!important}.no-padding-top{padding-top:0!important}.no-padding-left{padding-left:0!important}.no-padding-right{padding-right:0!important}.no-margin{margin:0!important}.no-margin-bottom{margin-bottom:0!important}.no-margin-top{margin-top:0!important}.no-margin-left{margin-left:0!important}.no-margin-right{margin-right:0!important}.no-border{border-width:0}.no-border-bottom{border-bottom-width:0}.no-border-top{border-top-width:0}.no-border-left{border-left-width:0}.no-border-right{border-right-width:0}.no-radius{border-radius:0!important}.no-text-shadow{text-shadow:none!important}.hr{display:block;height:0;overflow:hidden;font-size:0;border-width:1px 0 0;border-top:1px solid #E3E3E3;margin:12px 0;border-top-color:rgba(0,0,0,.11)}.hr-double{height:3px;border-top:1px solid #E3E3E3;border-bottom:1px solid #E3E3E3;border-top-color:rgba(0,0,0,.11);border-bottom-color:rgba(0,0,0,.11)}.hr-dotted,.hr.dotted{border-style:dotted}.hr-32,.hr32{margin:32px 0}.hr-30,.hr30{margin:30px 0}.hr-28,.hr28{margin:28px 0}.hr-26,.hr26{margin:26px 0}.hr-24,.hr24{margin:24px 0}.hr-22,.hr22{margin:22px 0}.hr-20,.hr20{margin:20px 0}.hr-18,.hr18{margin:18px 0}.hr-16,.hr16{margin:16px 0}.hr-14,.hr14{margin:14px 0}.hr-12,.hr12{margin:12px 0}.hr-10,.hr10{margin:10px 0}.hr-8,.hr8{margin:8px 0}.hr-6,.hr6{margin:6px 0}.hr-4,.hr4{margin:4px 0}.hr-2,.hr2{margin:2px 0}.space{max-height:1px;min-height:1px;overflow:hidden;margin:12px 0}[class*=vspace-]{display:none}.space-32,[class*=vspace-32]{max-height:1px;min-height:1px;overflow:hidden;margin:32px 0 31px}.space-30,[class*=vspace-30]{max-height:1px;min-height:1px;overflow:hidden;margin:30px 0 29px}.space-28,[class*=vspace-28]{max-height:1px;min-height:1px;overflow:hidden;margin:28px 0 27px}.space-26,[class*=vspace-26]{max-height:1px;min-height:1px;overflow:hidden;margin:26px 0 25px}.space-24,[class*=vspace-24]{max-height:1px;min-height:1px;overflow:hidden;margin:24px 0 23px}.space-22,[class*=vspace-22]{max-height:1px;min-height:1px;overflow:hidden;margin:22px 0 21px}.space-20,[class*=vspace-20]{max-height:1px;min-height:1px;overflow:hidden;margin:20px 0 19px}.space-18,[class*=vspace-18]{max-height:1px;min-height:1px;overflow:hidden;margin:18px 0 17px}.space-16,[class*=vspace-16]{max-height:1px;min-height:1px;overflow:hidden;margin:16px 0 15px}.space-14,[class*=vspace-14]{max-height:1px;min-height:1px;overflow:hidden;margin:14px 0 13px}.space-12,[class*=vspace-12]{max-height:1px;min-height:1px;overflow:hidden;margin:12px 0 11px}.space-10,[class*=vspace-10]{max-height:1px;min-height:1px;overflow:hidden;margin:10px 0 9px}.space-8,[class*=vspace-8]{max-height:1px;min-height:1px;overflow:hidden;margin:8px 0 7px}.space-6,[class*=vspace-6]{max-height:1px;min-height:1px;overflow:hidden;margin:6px 0 5px}.space-4,[class*=vspace-4]{max-height:1px;min-height:1px;overflow:hidden;margin:4px 0 3px}.space-2,[class*=vspace-2]{max-height:1px;min-height:1px;overflow:hidden;margin:2px 0 1px}.space-0,[class*=vspace-0]{max-height:1px;min-height:1px;overflow:hidden;margin:0}@media only screen and (max-width:479px){[class*=vspace-][class*="-xs"]{display:block}}@media only screen and (max-width:767px){[class*=vspace-][class*="-sm"]{display:block}}@media only screen and (max-width:991px){[class*=vspace-][class*="-md"]{display:block}}@media only screen and (max-width:1199px){[class*=vspace-][class*="-lg"]{display:block}}.header{line-height:28px;margin-bottom:16px;margin-top:18px;padding-bottom:4px;border-bottom:1px solid #CCC}.header.blue{border-bottom-color:#d5e3ef}.header.green{border-bottom-color:#cce2c1}.header.purple{border-bottom-color:#e0d1ea}.header.orange{border-bottom-color:#fdd0ac}.header.orange2{border-bottom-color:#fbd36b}.header.red{border-bottom-color:#f3cdc6}.header.grey{border-bottom-color:#c3c3c3}.header.pink{border-bottom-color:#f2e0eb}.header.pink2{border-bottom-color:#e69eb9}.header.light-blue{border-bottom-color:#dceefc}.header.light-red{border-bottom-color:#fec5c5}.header.light-green{border-bottom-color:#d2e7b5}.header.brown{border-bottom-color:#df9393}.header>.ace-icon{margin-right:2px}.action-buttons a{margin:0 3px;display:inline-block;opacity:.85;-webkit-transition:all .1s;-o-transition:all .1s;transition:all .1s}.action-buttons a:hover{text-decoration:none;opacity:1;-moz-transform:scale(1.2);-webkit-transform:scale(1.2);-o-transform:scale(1.2);-ms-transform:scale(1.2);transform:scale(1.2)}.navbar{margin:0;padding-left:0;padding-right:0;border-width:0;border-radius:0;-webkit-box-shadow:none;box-shadow:none;min-height:45px;background:#438eb9}.navbar .navbar-link,.navbar .navbar-text{color:#fff}.navbar .navbar-brand{color:#fff;font-size:24px;text-shadow:none;padding-top:10px;padding-bottom:10px;height:auto}.navbar .navbar-brand:focus,.navbar .navbar-brand:hover{color:#fff}@media only screen and (min-width:992px){.navbar-container{padding-left:10px;padding-right:10px}}.navbar-container.container{padding-left:0;padding-right:0}.ace-nav{height:100%;margin:0!important}.ace-nav>li{line-height:45px;height:45px;border-left:1px solid #E1E1E1;padding:0;position:relative;float:left}.ace-nav>li:first-child{border-left-width:0}.ace-nav>li>a{background-color:#2e6589;color:#FFF;display:block;line-height:inherit;text-align:center;height:100%;width:auto;min-width:50px;padding:0 8px;position:relative}.ace-nav>li>a>.ace-icon{display:inline-block;font-size:16px;color:#FFF;text-align:center;width:20px}.ace-nav>li>a>.badge{position:relative;top:-4px;left:2px;padding-right:5px;padding-left:5px}.ace-nav>li.open>a,.ace-nav>li>a:focus,.ace-nav>li>a:hover{background-color:#2c5976;color:#FFF}.ace-nav>li.grey>a{background-color:#555}.ace-nav>li.grey>a:focus,.ace-nav>li.grey>a:hover,.ace-nav>li.open.grey>a{background-color:#4b4b4b}.ace-nav>li.purple>a{background-color:#892e65}.ace-nav>li.open.purple>a,.ace-nav>li.purple>a:focus,.ace-nav>li.purple>a:hover{background-color:#762c59}.ace-nav>li.green>a{background-color:#2e8965}.ace-nav>li.green>a:focus,.ace-nav>li.green>a:hover,.ace-nav>li.open.green>a{background-color:#2c7659}.ace-nav>li.light-blue>a{background-color:#62a8d1}.ace-nav>li.light-blue>a:focus,.ace-nav>li.light-blue>a:hover,.ace-nav>li.open.light-blue>a{background-color:#579ec8}.ace-nav>li.light-blue2>a{background-color:#42a8e1}.ace-nav>li.light-blue2>a:focus,.ace-nav>li.light-blue2>a:hover,.ace-nav>li.open.light-blue2>a{background-color:#359fd9}.ace-nav>li.red>a{background-color:#b74635}.ace-nav>li.open.red>a,.ace-nav>li.red>a:focus,.ace-nav>li.red>a:hover{background-color:#a34335}.ace-nav>li.light-green>a{background-color:#9abc32}.ace-nav>li.light-green>a:focus,.ace-nav>li.light-green>a:hover,.ace-nav>li.open.light-green>a{background-color:#8ba832}.ace-nav>li.light-purple>a{background-color:#cb6fd7}.ace-nav>li.light-purple>a:focus,.ace-nav>li.light-purple>a:hover,.ace-nav>li.open.light-purple>a{background-color:#c263ce}.ace-nav>li.light-orange>a{background-color:#f79263}.ace-nav>li.light-orange>a:focus,.ace-nav>li.light-orange>a:hover,.ace-nav>li.open.light-orange>a{background-color:#f28653}.ace-nav>li.light-pink>a{background-color:#f4dae5}.ace-nav>li.light-pink>a:focus,.ace-nav>li.light-pink>a:hover,.ace-nav>li.open.light-pink>a{background-color:#eeccda}.ace-nav>li.dark>a{background-color:#404040}.ace-nav>li.dark>a:focus,.ace-nav>li.dark>a:hover,.ace-nav>li.open.dark>a{background-color:#363636}.ace-nav>li.white-opaque>a{background-color:rgba(255,255,255,.8)}.ace-nav>li.open.white-opaque>a,.ace-nav>li.white-opaque>a:focus,.ace-nav>li.white-opaque>a:hover{background-color:rgba(245,245,245,.8)}.ace-nav>li.dark-opaque>a,.ace-nav>li.dark-opaque>a:focus,.ace-nav>li.dark-opaque>a:hover,.ace-nav>li.open.dark-opaque>a{background-color:rgba(0,0,0,.2)}.ace-nav>li.transparent>a{background-color:transparent}.ace-nav>li.open.transparent>a,.ace-nav>li.transparent>a:focus,.ace-nav>li.transparent>a:hover{background-color:rgba(0,0,0,.1)}.ace-nav>li.light-10>a{background-color:rgba(255,255,255,.1)}.ace-nav>li.light-10>a:focus,.ace-nav>li.light-10>a:hover,.ace-nav>li.open.light-10>a{background-color:rgba(255,255,255,.2)}.ace-nav>li.dark-10>a{background-color:rgba(0,0,0,.1)}.ace-nav>li.dark-10>a:focus,.ace-nav>li.dark-10>a:hover,.ace-nav>li.open.dark-10>a{background-color:rgba(0,0,0,.2)}.ace-nav>li.margin-4{margin-left:4px}.ace-nav>li.margin-3{margin-left:3px}.ace-nav>li.margin-2{margin-left:2px}.ace-nav>li.margin-1{margin-left:1px}.ace-nav>li.no-border{border-width:0!important}.ace-nav>li .dropdown-menu{z-index:1031}.ace-nav .nav-user-photo{margin:-4px 8px 0 0;border-radius:100%;border:2px solid #FFF;max-width:40px}.ace-nav li.dropdown-footer a .ace-icon{display:inline-block;width:1.25em;text-align:center}@media only screen and (max-width:767px){.ace-nav>li:nth-last-child(4)>.dropdown-menu.dropdown-menu-right{right:-100px}.ace-nav>li:nth-last-child(4)>.dropdown-menu.dropdown-menu-right:after,.ace-nav>li:nth-last-child(4)>.dropdown-menu.dropdown-menu-right:before{right:120px}.ace-nav>li:nth-last-child(3)>.dropdown-menu.dropdown-menu-right{right:-80px}.ace-nav>li:nth-last-child(3)>.dropdown-menu.dropdown-menu-right:after,.ace-nav>li:nth-last-child(3)>.dropdown-menu.dropdown-menu-right:before{right:100px}.user-menu.dropdown-close.dropdown-menu-right{right:0!important}}@media only screen and (min-width:480px) and (max-width:767px){.navbar.navbar-collapse .ace-nav>li:nth-last-child(2):nth-child(1)>.dropdown-menu.dropdown-menu-right,.navbar.navbar-collapse .ace-nav>li:nth-last-child(2):nth-child(2)>.dropdown-menu.dropdown-menu-right{left:auto;right:-60px}.navbar.navbar-collapse .ace-nav>li:nth-last-child(2):nth-child(1)>.dropdown-menu.dropdown-menu-right:after,.navbar.navbar-collapse .ace-nav>li:nth-last-child(2):nth-child(1)>.dropdown-menu.dropdown-menu-right:before,.navbar.navbar-collapse .ace-nav>li:nth-last-child(2):nth-child(2)>.dropdown-menu.dropdown-menu-right:after,.navbar.navbar-collapse .ace-nav>li:nth-last-child(2):nth-child(2)>.dropdown-menu.dropdown-menu-right:before{right:80px;left:auto}}@media only screen and (max-width:480px){.ace-nav>li:nth-last-child(4)>.dropdown-menu.dropdown-menu-right{right:-120px}.ace-nav>li:nth-last-child(4)>.dropdown-menu.dropdown-menu-right:after,.ace-nav>li:nth-last-child(4)>.dropdown-menu.dropdown-menu-right:before{right:140px}.ace-nav>li:nth-last-child(3)>.dropdown-menu.dropdown-menu-right{right:-90px}.ace-nav>li:nth-last-child(3)>.dropdown-menu.dropdown-menu-right:after,.ace-nav>li:nth-last-child(3)>.dropdown-menu.dropdown-menu-right:before{right:110px}.ace-nav>li:nth-last-child(2)>.dropdown-menu.dropdown-menu-right{right:-50px}.ace-nav>li:nth-last-child(2)>.dropdown-menu.dropdown-menu-right:after,.ace-nav>li:nth-last-child(2)>.dropdown-menu.dropdown-menu-right:before{right:70px}}@media only screen and (max-width:479px){.ace-nav>li:nth-last-child(4)>.dropdown-menu.dropdown-menu-right{left:-10px;right:auto}.ace-nav>li:nth-last-child(4)>.dropdown-menu.dropdown-menu-right:after,.ace-nav>li:nth-last-child(4)>.dropdown-menu.dropdown-menu-right:before{right:auto;left:30px}.ace-nav>li:nth-last-child(3)>.dropdown-menu.dropdown-menu-right{left:-50px;right:auto}.ace-nav>li:nth-last-child(3)>.dropdown-menu.dropdown-menu-right:after,.ace-nav>li:nth-last-child(3)>.dropdown-menu.dropdown-menu-right:before{left:75px;right:auto}.ace-nav>li:nth-last-child(2)>.dropdown-menu.dropdown-menu-right{left:-70px;right:auto}.ace-nav>li:nth-last-child(2)>.dropdown-menu.dropdown-menu-right:after,.ace-nav>li:nth-last-child(2)>.dropdown-menu.dropdown-menu-right:before{left:90px;right:auto}}@media only screen and (max-width:319px){.ace-nav>li:nth-last-child(2)>.dropdown-menu.dropdown-menu-right{left:-110px;right:auto}.ace-nav>li:nth-last-child(2)>.dropdown-menu.dropdown-menu-right:after,.ace-nav>li:nth-last-child(2)>.dropdown-menu.dropdown-menu-right:before{left:130px;right:auto}.ace-nav>li:nth-child(2):nth-last-child(2)>.dropdown-menu.dropdown-menu-right{left:-85px;right:auto}.ace-nav>li:nth-child(2):nth-last-child(2)>.dropdown-menu.dropdown-menu-right:after,.ace-nav>li:nth-child(2):nth-last-child(2)>.dropdown-menu.dropdown-menu-right:before{left:105px;right:auto}.ace-nav>li:nth-child(1):nth-last-child(3)>.dropdown-menu.dropdown-menu-right{left:-35px;right:auto}.ace-nav>li:nth-child(1):nth-last-child(3)>.dropdown-menu.dropdown-menu-right:after,.ace-nav>li:nth-child(1):nth-last-child(3)>.dropdown-menu.dropdown-menu-right:before{left:55px;right:auto}.ace-nav>li:nth-child(1):nth-last-child(2)>.dropdown-menu.dropdown-menu-right{left:-60px;right:auto}.ace-nav>li:nth-child(1):nth-last-child(2)>.dropdown-menu.dropdown-menu-right:after,.ace-nav>li:nth-child(1):nth-last-child(2)>.dropdown-menu.dropdown-menu-right:before{left:75px;right:auto}}@media only screen and (max-width:479px){.navbar:not(.navbar-collapse) .navbar-header{float:none!important;display:block}.navbar:not(.navbar-collapse) .ace-nav{display:block;float:none!important;text-align:center;background-color:rgba(0,0,0,.15);border:1px solid rgba(0,0,0,.1);border-width:1px 0 0;letter-spacing:-3px}.navbar:not(.navbar-collapse) .ace-nav>li{display:inline-block;float:none!important;text-align:left;letter-spacing:normal}.navbar:not(.navbar-collapse) .ace-nav>li:first-child{border-left:1px solid rgba(255,255,255,.4)}.navbar:not(.navbar-collapse) .ace-nav>li:last-child{border-right:1px solid rgba(255,255,255,.4)}}@media only screen and (max-width:319px){.ace-nav>li>a{padding:0 5px!important}}.user-menu>li>a{padding:4px 12px}.user-menu>li>a>.ace-icon{margin-right:6px;font-size:120%}.user-info{max-width:100px;display:inline-block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left;vertical-align:top;line-height:15px;position:relative;top:6px}.user-info small{display:block}@media (min-width:480px) and (max-width:540px),(max-width:360px){.navbar:not(.navbar-collapse) .navbar-buttons .user-menu{padding-top:42px!important}.navbar:not(.navbar-collapse) .navbar-buttons .nav-user-photo{margin-right:0}.navbar:not(.navbar-collapse) .navbar-buttons .user-info{position:absolute!important;margin-top:40px;margin-left:1px;right:2px;z-index:1032;color:#777;font-size:14px;width:156px;max-width:156px;padding-left:8px;padding-right:8px;height:32px;line-height:26px!important;display:none;border-bottom:1px solid #E5E5E5;text-align:center;vertical-align:none;cursor:text}.navbar:not(.navbar-collapse) .navbar-buttons .user-info>small{display:inline;opacity:1}li.open .user-info{display:inline-block!important}}@media (max-width:360px){.navbar.navbar-collapse .navbar-buttons .user-menu{padding-top:42px!important}.navbar.navbar-collapse .navbar-buttons .nav-user-photo{margin-right:0}.navbar.navbar-collapse .navbar-buttons .user-info{position:absolute!important;margin-top:40px;margin-left:1px;right:2px;z-index:1032;color:#777;font-size:14px;width:156px;max-width:156px;padding-left:8px;padding-right:8px;height:32px;line-height:26px!important;display:none;border-bottom:1px solid #E5E5E5;text-align:center;vertical-align:none;cursor:text}.navbar.navbar-collapse .navbar-buttons .user-info>small{display:inline;opacity:1}li.open .user-info{display:inline-block!important;right:2px}}@media (min-width:992px){.user-min .user-menu{padding-top:42px!important}.user-min .nav-user-photo{margin-right:0}.user-min .user-info{position:absolute!important;margin-top:40px;margin-left:1px;z-index:1032;color:#777;font-size:14px;width:156px;max-width:156px;padding-left:8px;padding-right:8px;height:32px;line-height:26px!important;display:none;border-bottom:1px solid #E5E5E5;text-align:center;vertical-align:none;cursor:text}.user-min .user-info>small{display:inline;opacity:1}.user-min .user-info{right:-3px}.user-min.open .user-info{display:inline-block!important}}@media only screen and (max-width:991px){.navbar.navbar-collapse{max-height:none}.navbar .navbar-collapse,.navbar .navbar-header{margin-left:0!important;margin-right:0!important}.navbar.navbar-collapse .navbar-header{float:none!important;min-height:45px}.navbar.navbar-collapse .navbar-buttons{min-height:0;padding-left:0;padding-right:0;border:1px solid rgba(255,255,255,.4);border-width:1px 0 0;width:100%}.navbar.navbar-collapse .navbar-buttons.in{overflow:visible!important}.navbar.navbar-collapse .navbar-buttons>.ace-nav{display:block;float:none!important;text-align:center;background-color:transparent!important;border-width:0;letter-spacing:-3px}.navbar.navbar-collapse .navbar-buttons>.ace-nav>li{display:inline-block;float:none!important;text-align:left;letter-spacing:normal}.navbar.navbar-collapse .navbar-buttons>.ace-nav>li:first-child{border-left:1px solid rgba(255,255,255,.4)}.navbar.navbar-collapse .navbar-buttons>.ace-nav>li:last-child{border-right:1px solid rgba(255,255,255,.4)}}.container-fluid>.navbar-buttons,.container>.navbar-buttons{padding-right:0!important}@media only screen and (max-height:400px){.navbar-fixed-top .navbar-collapse{max-height:280px}}@media only screen and (max-height:360px){.navbar-fixed-top .navbar-collapse{max-height:240px}}@media only screen and (max-height:320px){.navbar-fixed-top .navbar-collapse{max-height:200px}}@media only screen and (max-height:280px){.navbar-fixed-top .navbar-collapse{max-height:160px}}@media only screen and (max-height:240px){.navbar-fixed-top .navbar-collapse{max-height:120px}}.navbar .navbar-nav>li{border:1px solid rgba(0,0,0,.2);border-width:0 1px 0 0}.navbar .navbar-nav>li:first-child{border-width:0 1px}.navbar .navbar-nav>li>a{padding-top:12px;padding-bottom:11px;height:45px;background-color:transparent;font-size:13px;color:#fff;text-shadow:0 1px 0 rgba(0,0,0,.25)}.navbar .navbar-nav>li.open>a,.navbar .navbar-nav>li>a:focus,.navbar .navbar-nav>li>a:hover{background-color:rgba(0,0,0,.1)!important;color:#fff!important}.navbar .navbar-nav>li>.dropdown-menu>li>a{line-height:2}.navbar-nav .dropdown-menu>li>a>.ace-icon{display:inline-block;width:20px}.navbar-nav>li>.dropdown-menu{z-index:1033}@media only screen and (max-width:991px){.navbar.navbar-collapse .navbar-menu{float:none!important;clear:both}.navbar.navbar-collapse .navbar-menu .dropdown-menu:after,.navbar.navbar-collapse .navbar-menu .dropdown-menu:before{display:none!important}.navbar .navbar-nav{margin:0 -6px}.navbar .navbar-nav>li,.navbar .navbar-nav>li:first-child{border-width:1px 0 0}.navbar .navbar-nav .dropdown-menu{float:none;position:relative;background-color:transparent;box-shadow:none;border-width:0}.navbar .navbar-nav .dropdown-menu>li>a{color:#FFF!important}.navbar .navbar-nav .dropdown-menu>li>a:hover{background-color:rgba(0,0,0,.07)!important}.navbar .navbar-nav .dropdown-menu>li>a>.ace-icon{color:#FFF!important}.navbar .navbar-nav .dropdown-hover>.dropdown-menu{left:32px!important;right:auto!important;top:auto!important;width:80%!important;width:calc(100% - 32px)}}.navbar-form.form-search{margin-top:9px;margin-bottom:0}.navbar-form.form-search .form-group{margin-bottom:0}.navbar-form.form-search input[type=text]{width:100px}.navbar-form input[type=text]{font-size:13px;line-height:1.4;padding-top:4px;padding-bottom:4px;border-width:0}@media only screen and (max-width:991px){.navbar-form .form-group{display:inline-block;width:50%;margin-bottom:0;vertical-align:middle}.navbar-form.form-search input[type=text]{width:100%}.navbar-nav+.navbar-form{margin-top:0}.navbar .navbar-collapse,.navbar .navbar-form{border-color:rgba(255,255,255,.4)}.navbar .navbar-nav>li:first-child{border-top-width:0}}@media only screen and (max-width:480px){.navbar-form .form-group{width:80%}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-left:12px;padding-right:12px}@media only screen and (min-width:768px) and (max-width:991px){.navbar.navbar-collapse{background-color:transparent}.navbar.navbar-collapse:before{background:#438eb9;content:"";display:block;position:absolute;min-height:inherit;left:0;right:0;top:0;z-index:-1;border-radius:inherit}.navbar.navbar-collapse .navbar-container{background-color:#438eb9}}.navbar .navbar-toggle{border:1px solid transparent;width:40px;height:35px;line-height:0;padding:0 0 1px;text-align:center}.navbar .navbar-toggle.pull-right{margin:5px 6px 4px 0}.navbar .navbar-toggle.pull-left{margin:5px 0 4px 6px}.navbar .navbar-toggle:active{top:1px}.navbar .navbar-toggle.navbar-toggle-img{width:auto;height:auto;overflow:hidden;padding:0;border-width:0}.navbar .navbar-toggle.navbar-toggle-img>img{border-radius:inherit;max-height:35px;border-width:0}.navbar .navbar-toggle .icon-bar{background-color:#FFF;border-radius:0;width:24px;margin-left:7px}.sidebar{width:190px;float:left;position:static;padding-left:0;padding-right:0}.sidebar:before{content:"";display:block;width:inherit;position:absolute;top:0;bottom:0;z-index:-1;background-color:inherit;border-style:inherit;border-color:inherit;border-width:inherit}.nav-list{margin:0;padding:0;list-style:none}.nav-list .nav-header,.nav-list>li,.nav-list>li>a{margin:0}.nav-list li>a:focus{outline:0}.nav-list>li{display:block;position:relative;float:none;padding:0;border-style:solid;border-width:1px 0 0}.nav-list>li:last-child{border-bottom-width:1px}.nav-list>li.active>a{font-weight:700}.nav-list>li>a{display:block;height:39px;line-height:17px;padding-left:7px;text-shadow:none!important;font-size:13px;text-decoration:none}.nav-list>li>a>.menu-icon{display:inline-block;min-width:30px;margin-right:2px;vertical-align:sub;text-align:center;font-size:18px;font-weight:400}.nav-list>li:before{display:none;content:"";position:absolute;top:-1px;left:0;z-index:1;height:41px;width:3px;max-width:3px;overflow:hidden;background-color:#629cc9}@media only screen and (min-width:992px){.main-container.container .sidebar:not(.h-sidebar) .nav-list>li:before{left:-2px}}.nav-list>li:hover:before{display:block}.nav-list>li a>.arrow{display:block;width:14px!important;height:14px;line-height:14px;text-shadow:none;font-size:18px;position:absolute;right:10px;top:12px;padding:0;text-align:center}.nav-list>li.separator{height:3px;background-color:transparent;position:static;margin:1px 0;-webkit-box-shadow:none;box-shadow:none}.nav-list>li.active .submenu{display:block}.nav-list>li .submenu{display:none;list-style:none;margin:0;padding:0;line-height:1.5;position:relative}.nav-list>li .submenu>li{margin-left:0;position:relative}.nav-list>li .submenu>li>a{display:block;position:relative;padding:7px 0 9px 37px;margin:0;border-top-width:1px;border-top-style:dotted}.nav-list>li .submenu>li>a:hover{text-decoration:none}.nav-list>li .submenu>li a>.menu-icon{display:none;font-size:12px;font-weight:400;width:18px;height:auto;line-height:12px;text-align:center;position:absolute;left:10px;top:11px;z-index:1;background-color:inherit}.nav-list>li .submenu>li.active>a>.menu-icon,.nav-list>li .submenu>li:hover>a>.menu-icon{display:inline-block}.nav-list>li>.submenu{border-top:1px solid}.nav-list>li>.submenu>li:before{content:"";display:block;width:7px;position:absolute;z-index:1;left:20px;top:17px;border:1px dotted;border-width:1px 0 0}.nav-list>li>.submenu:before{content:"";display:block;position:absolute;z-index:1;left:18px;top:0;bottom:0;border:1px dotted;border-width:0 0 0 1px}.nav-list li.active>a>.arrow,.nav-list li.open>a>.arrow,.nav-list li:hover>a>.arrow{color:inherit}.nav-list>li>a>.menu-icon,no_such_element:-o-prefocus{vertical-align:middle}.nav-list>li>.submenu li>.submenu{display:none}.nav-list>li>.submenu li.active>.submenu{display:block}.nav-list>li>.submenu a>.arrow{right:10px;top:10px;font-size:16px}.nav-list>li>.submenu>li:first-child>a{border-top-width:0}.nav-list>li>.submenu li>.submenu>li{line-height:18px}.nav-list>li>.submenu li>.submenu>li:before{display:none}.nav-list>li>.submenu li>.submenu>li>a{margin-left:20px;padding-left:22px}.nav-list>li>.submenu li>.submenu>li>.submenu>li>a{margin-left:20px;padding-left:38px}.nav-list>li>.submenu li>.submenu>li a>.menu-icon{display:inline-block;width:auto;position:static;background-color:transparent;margin-right:4px;color:inherit}.nav-list>li>.submenu li>.submenu>li a .arrow,.nav-list>li>.submenu li>.submenu>li a .menu-icon{color:inherit}.nav-list>li>.submenu li.open:not(.hover)>a>.menu-icon{display:inline-block}.nav-list a .badge,.nav-list a .label{position:absolute;top:9px;right:10px;opacity:.88;font-size:12px;padding-left:6px;padding-right:6px}.nav-list a .badge .ace-icon,.nav-list a .label .ace-icon{vertical-align:middle;margin:0}.nav-list a.dropdown-toggle .badge,.nav-list a.dropdown-toggle .label{right:26px}.nav-list li:hover>a .badge,.nav-list li:hover>a .label{opacity:1}.nav-list .submenu .submenu a .badge,.nav-list .submenu .submenu a .label{top:6px}.sidebar.sidebar-fixed{position:fixed;top:auto;float:none!important;z-index:1027}.sidebar.sidebar-fixed:before{height:5000px;top:auto;bottom:auto}body.mob-safari .sidebar.sidebar-fixed{top:45px}@media (max-width:479px){body.mob-safari .navbar-fixed-top:not(.navbar-collapse)+.main-container .sidebar-fixed{top:90px}}@media (max-width:991px){body.mob-safari .navbar-fixed-top+.main-container .sidebar.responsive{top:45px}}@media (max-width:479px){body.mob-safari .navbar-fixed-top+.main-container .sidebar.responsive{top:90px}}@media only screen and (max-width:991px){.responsive.sidebar-fixed{left:auto;margin-left:auto}.navbar-fixed-top+.main-container>.responsive{position:fixed;left:auto;margin-left:auto;-moz-backface-visibility:hidden}.navbar-fixed-top+.main-container>.menu-toggler+.responsive{position:absolute;left:190px;margin-left:-190px;-moz-backface-visibility:visible}.navbar-fixed-top+.main-container>.menu-toggler+.responsive.sidebar-fixed{position:fixed;left:auto;margin-left:auto;-moz-backface-visibility:hidden}}@media only screen and (max-width:991px){.sidebar.responsive.sidebar-fixed{position:fixed;left:auto;margin-left:auto}.main-container .menu-toggler.fixed{position:fixed;left:auto;z-index:1026;-moz-backface-visibility:hidden}.sidebar.sidebar-fixed.responsive-max{position:fixed;left:auto;margin-left:auto}}.sidebar .sidebar-toggle{border-style:solid;border-width:0 0 1px;text-align:center;padding:3px 0;position:relative}.sidebar .sidebar-toggle>.ace-icon{padding:0 5px;line-height:18px;cursor:pointer;font-size:14px;border-radius:100%;border:1px solid;position:relative}.sidebar .sidebar-toggle:before{content:"";display:block;height:0;border-top:1px solid;border-color:inherit;position:absolute;left:15px;right:15px;top:13px}.sidebar .sidebar-shortcuts{text-align:center;min-height:40px;margin-bottom:0;overflow:hidden;position:relative;border:0 solid}.sidebar .sidebar-shortcuts-large{line-height:37px}.sidebar .sidebar-shortcuts-large>.btn{text-align:center;width:41px;line-height:24px;padding:0;border-width:4px}.sidebar .sidebar-shortcuts-large>.btn>.ace-icon{margin:0}.sidebar .sidebar-shortcuts-mini{display:none;font-size:0;width:42px;padding-top:2px;padding-bottom:2px}.sidebar .sidebar-shortcuts-mini>.btn{border-width:0!important;font-size:0;line-height:0;padding:8px!important;margin:1px;border-radius:0!important;opacity:.85;filter:alpha(opacity=85)}@media screen and (-webkit-min-device-pixel-ratio:0){.sidebar .sidebar-shortcuts-mini>.btn,.sidebar ::safari-only{margin:0}}.nav-list li.active>a:after{display:block;content:"";position:absolute;right:0;top:4px;border:8px solid transparent;border-width:14px 10px}.nav-list li.open>a:after{display:none}.nav-list li.active.no-active-child>a:after{display:block}.nav-list>li li.active>a:after{top:2px;border-width:14px 8px}.nav-list li.active:not(.open) li.active>a:after{display:none!important}@media (min-width:992px){.sidebar.compact,.sidebar.compact.navbar-collapse{width:105px}.sidebar.compact .sidebar-shortcuts{max-height:40px}.sidebar.compact .nav-list>li:before{height:auto;bottom:-1px}.sidebar.compact .nav-list>li>a{height:auto;line-height:16px;padding:2px 0 8px;text-align:center}.sidebar.compact .nav-list>li>a>.menu-icon{display:block;margin:0;vertical-align:inherit;line-height:32px;height:32px;font-size:20px}.sidebar.compact .nav-list>li>a>.arrow{display:none}.sidebar.compact .nav-list a .badge,.sidebar.compact .nav-list a .label{right:12px}.sidebar.compact .nav-list>li.active>.submenu,.sidebar.compact .nav-list>li.open>.submenu{display:none}.sidebar.compact+.main-content{margin-left:105px}}@media (min-width:992px) and (max-width:991px){.sidebar.compact+.main-content{margin-left:0}.sidebar.navbar-collapse.compact .nav-list>li>a{text-align:left;height:39px;line-height:37px;padding:0 16px 0 7px}.sidebar.navbar-collapse.compact .nav-list>li>a>.menu-icon{display:inline-block;vertical-align:sub;height:auto;line-height:inherit;margin:0 2px 0 0;font-size:18px}.sidebar.navbar-collapse.compact .nav-list>li>a>.arrow,.sidebar.navbar-collapse.compact .nav-list>li>a>.menu-text{display:inline}.sidebar.navbar-collapse.compact+.main-content{margin-left:0}}@media only screen and (min-width:992px){.nav-list li.hover>.submenu{position:absolute;left:100%;margin-left:-2px;top:-10px;bottom:auto;z-index:1026;width:190px;border:1px solid;display:none!important}.nav-list li.hover:hover>.submenu{display:block!important}.nav-list li.hover>.submenu:before,.nav-list li.hover>.submenu>li:before{display:none}.nav-list li.hover.active>a:after{display:block}.nav-list li.hover.active:hover>a.dropdown-toggle:after{display:none}.nav-list li.hover .submenu>li.active>a:after{display:none!important}.nav-list li.hover>.submenu.bottom{top:auto;bottom:-10px}.nav-list li.hover>.submenu.bottom:after,.nav-list li.hover>.submenu.bottom:before{top:auto;bottom:18px}.nav-list li.hover>.submenu{padding:0 2px}.nav-list li.hover>.submenu>li>a{margin-top:2px;margin-bottom:2px;padding-left:18px;border-top-width:0}.nav-list>li.hover>.submenu>li.active>a{font-weight:700}.nav-list>li>.submenu li.hover>.submenu>li>a{padding-left:12px!important;margin-left:auto!important}.nav-list>li>.submenu li.hover>.submenu>li>a>.menu-icon{margin-right:2px}.nav-list>li .submenu>li.hover>a{padding-left:22px}.nav-list>li .submenu>li.hover>a>.menu-icon{left:4px}}@media (min-width:992px) and (max-width:991px){.sidebar.navbar-collapse .nav-list li.hover>.submenu{position:relative;left:auto;top:auto;z-index:auto;margin:auto;padding:0;width:auto;-webkit-box-shadow:none;box-shadow:none;border-width:0}.sidebar.navbar-collapse .nav-list li.hover>.submenu:before,.sidebar.navbar-collapse .nav-list li.hover>.submenu>li:before{display:block}.sidebar.navbar-collapse .nav-list li.hover>.submenu li>a{padding-left:37px}.sidebar.navbar-collapse .nav-list>li.hover>.submenu{border-top-width:1px}.sidebar.navbar-collapse .nav-list li.hover>.submenu>li>a>.menu-icon{background-color:inherit;margin-right:auto;width:18px;position:absolute}.sidebar.navbar-collapse .nav-list>li .submenu>li.hover>a>.menu-icon{left:10px}.sidebar.navbar-collapse .nav-list li.hover>.submenu>li.active>a{font-weight:400}.sidebar.navbar-collapse .nav-list li.hover>.submenu>li.active>a>.menu-icon,.sidebar.navbar-collapse .nav-list li.hover>.submenu>li:hover>a>.menu-icon{display:inline-block}.sidebar.navbar-collapse .nav-list>li>.submenu li.hover>.submenu{padding-left:0;padding-right:0}.sidebar.navbar-collapse .nav-list>li>.submenu li.hover>.submenu>li>a{padding-left:22px!important;margin-left:20px!important}.sidebar.navbar-collapse .nav-list>li>.submenu li.hover>.submenu>li>a>.menu-icon{display:inline-block;width:auto;position:static;background-color:transparent;margin-right:4px}.sidebar.navbar-collapse .nav-list>li>.submenu li>.submenu>li.hover>.submenu>li>a{margin-left:20px!important;padding-left:38px!important}.sidebar.navbar-collapse .nav-list li.hover>.submenu>li>a{border-top-width:1px;margin-top:0;margin-bottom:0}.sidebar.navbar-collapse .nav-list>li.hover>.submenu>li:first-child>a{border-top-width:0}.sidebar.navbar-collapse .nav-list li.hover:hover>.submenu,.sidebar.navbar-collapse .nav-list li.hover>.arrow,.sidebar.navbar-collapse .nav-list li.hover>.submenu{display:none!important}.sidebar.navbar-collapse .nav-list li.hover.active>.submenu{display:block!important}.sidebar.navbar-collapse .nav-list li.hover>.submenu.nav-hide{display:none!important}.sidebar.navbar-collapse .nav-list li.hover>.submenu.nav-show{display:block!important}}@media (min-width:992px) and (max-width:991px){.sidebar.navbar-collapse.compact .nav-list>li.hover.active>a:after{display:none}}.nav-list li>.arrow{display:none;position:absolute;top:8px;right:1px;z-index:1027}.nav-list li>.arrow:after,.nav-list li>.arrow:before{border:1px solid transparent;display:block;height:0;width:0;position:absolute;left:-20px;top:0;right:auto;bottom:auto;content:"";border-width:10px}.nav-list li>.arrow:before{z-index:1;left:-21px}.nav-list li>.arrow:after{z-index:2}.nav-list li:hover>a+.arrow{display:none}@media only screen and (min-width:992px){.nav-list li.hover:hover>a.dropdown-toggle+.arrow{display:block}}.sidebar.menu-min,.sidebar.menu-min.compact,.sidebar.menu-min.navbar-collapse{width:43px}.sidebar.menu-min+.main-content{margin-left:43px}.sidebar.menu-min .nav-list a .badge,.sidebar.menu-min .nav-list a .label{position:relative;top:-1px;right:auto;left:4px}.sidebar.menu-min .nav-list .submenu .submenu a .badge,.sidebar.menu-min .nav-list .submenu .submenu a .label{top:0}.sidebar.menu-min .nav-list>li>a{position:relative;height:39px;line-height:37px;padding:0}.sidebar.menu-min .nav-list>li>a>.menu-icon{font-size:18px;height:auto;line-height:inherit;display:inline-block;vertical-align:sub;margin-right:0;width:44px}.sidebar.menu-min .nav-list>li>a>.menu-text{display:none;text-align:left;position:absolute;top:-1px;left:42px;z-index:1025;width:176px;height:41px;line-height:38px;padding-left:12px;border:1px solid}.sidebar.menu-min .nav-list>li>a.dropdown-toggle>.menu-text{top:-1px;border-width:1px 1px 0}.sidebar.menu-min .nav-list>li>a .arrow{display:none}.sidebar.menu-min .nav-list>li:hover>a>.menu-text{display:block}.sidebar.menu-min .nav-list>li.active>a:after{border-width:10px 6px;top:8px}.sidebar.menu-min .nav-list>li.active.open>a:after{display:block}.sidebar.menu-min .nav-list>li.active.open li.active>a:after{display:none}.sidebar.menu-min .nav-list>li>.submenu{position:absolute;z-index:1028;left:42px;top:-1px;margin-top:40px;padding-bottom:2px;width:176px;display:none!important}.sidebar.menu-min .nav-list>li>.submenu:before{display:none}.sidebar.menu-min .nav-list>li>.submenu:after{content:"";display:block;height:1px;width:1px;position:absolute;right:-1px;top:-1px;border-right:1px solid;border-right-color:inherit}.sidebar.menu-min .nav-list>li>.submenu li:before{display:none}.sidebar.menu-min .nav-list>li>.submenu li>a{margin-left:0;padding-left:22px}.sidebar.menu-min .nav-list>li>.submenu li>a>.menu-icon{left:4px}.sidebar.menu-min .nav-list>li.hover>.submenu{padding-bottom:0}.sidebar.menu-min .nav-list>li.open>.submenu{display:none}.sidebar.menu-min .nav-list>li:hover>.submenu{display:block!important}.sidebar.menu-min .nav-list>li>.arrow{top:10px}.sidebar.menu-min .nav-list>li>.arrow:after,.sidebar.menu-min .nav-list>li>.arrow:before{border-width:8px;left:-16px}.sidebar.menu-min .nav-list>li>.arrow:before{left:-17px}.sidebar.menu-min .nav-list li>.arrow{right:-1px}.sidebar.menu-min .nav-list>li:hover>.arrow{display:block}.sidebar.menu-min .nav-list>li.pull_up>.arrow{z-index:1029}.sidebar.menu-min .nav-list>li.pull_up>.arrow:after,.sidebar.menu-min .nav-list>li.pull_up>.arrow:before{border-width:10px;left:-20px}.sidebar.menu-min .nav-list>li.pull_up>.arrow:before{left:-21px}.sidebar.menu-min .sidebar-shortcuts{position:relative;overflow:visible;z-index:1}.sidebar.menu-min .sidebar-shortcuts-mini{display:block}.sidebar.menu-min .sidebar-shortcuts-large{display:none;position:absolute;top:0;left:42px;width:182px;padding:0 2px 3px;border:1px solid;border-top-width:0}.sidebar.menu-min .sidebar-shortcuts:hover .sidebar-shortcuts-large{display:block}.sidebar.menu-min .sidebar-toggle:before{left:5px;right:5px}.sidebar.menu-min .sidebar-toggle>.ace-icon{font-size:13px;padding:0 4px;line-height:15px;border-width:1px}.sidebar.menu-min .nav-list>li>.submenu li>.submenu>li>a{margin-left:2px!important;padding-left:30px}.sidebar.menu-min .nav-list>li>.submenu li>.submenu>li>.submenu>li>a{margin-left:2px!important;padding-left:45px}.sidebar.menu-min .nav-list li.active.open>.submenu>li.active>a:after,.sidebar.menu-min .nav-list>li.active.open:hover>a:after,.sidebar.menu-min .nav-list>li.active:hover:after,.sidebar.menu-min .nav-list>li.active:hover>a:after,.sidebar.menu-min .nav-list>li>.submenu li.active>a:after{display:none}@media only screen and (min-width:992px){.sidebar.menu-min .nav-list li.hover>.submenu{margin-left:0}.sidebar.menu-min .nav-list>li>.submenu li.hover>.submenu>li>a,.sidebar.menu-min .nav-list>li>.submenu li>.submenu>li.hover>.submenu>li>a{margin-left:0!important}}@media (min-width:992px){.sidebar.menu-min.compact .nav-list>li>a{height:39px;line-height:37px;padding:0 16px 0 7px;position:relative}.sidebar.menu-min.compact .nav-list>li>a>.menu-icon{font-size:18px;height:auto;line-height:inherit;display:inline-block;vertical-align:sub;width:auto}}@media only screen and (min-width:992px){.navbar.h-navbar{-webkit-box-shadow:0 2px 4px 0 rgba(0,0,0,.25);box-shadow:0 2px 4px 0 rgba(0,0,0,.25)}.sidebar.h-sidebar{position:relative;float:none!important;width:auto!important;margin-top:17px;border-width:0!important;box-shadow:none}.sidebar.h-sidebar.sidebar-fixed{position:fixed}.sidebar.h-sidebar:before{display:block;position:absolute;z-index:-1;left:0!important;right:0!important;top:-17px;bottom:auto;height:17px;width:auto;border-width:0;border-bottom:1px solid;border-bottom-color:inherit}.sidebar.h-sidebar.hide-before .nav-list>li:before{top:0}.sidebar.h-sidebar .nav-list{border-width:0;border-bottom:2px solid #79b0ce}.sidebar.h-sidebar .nav-list>li{float:left;border-width:0 1px;margin-left:-1px}.sidebar.h-sidebar .nav-list>li:before{left:-1px;right:-1px;bottom:auto;top:-2px;max-width:none;width:auto;height:2px;border-width:0}.sidebar.h-sidebar .nav-list>li.active:before{display:block}.sidebar.h-sidebar .nav-list>li.active:after{display:none}.sidebar.h-sidebar .nav-list>li:hover{z-index:1026}.sidebar.h-sidebar .nav-list>li.active{z-index:1027}.sidebar.h-sidebar .nav-list>li:first-child{border-left-width:0;margin-left:0}.sidebar.h-sidebar .sidebar-shortcuts+.nav-list>li:first-child{border-left-width:1px;margin-left:-1px}.sidebar.h-sidebar .nav-list>li>a{line-height:22px!important;height:auto!important;padding:10px 14px!important}.sidebar.h-sidebar .nav-list>li>a>.menu-icon{display:block!important;margin:1px 0 4px;line-height:inherit;width:auto}.sidebar.h-sidebar .nav-list>li>a>.arrow{display:none}.sidebar.h-sidebar .nav-list>li.hover.pull_right{float:none!important}.sidebar.h-sidebar .nav-list>li.hover>.submenu{top:100%;left:1px;margin-top:auto;margin-left:-2px;width:190px;z-index:1026}.sidebar.h-sidebar .nav-list>li.hover.pull_right>.submenu{left:auto;right:1px}.sidebar.h-sidebar .nav-list>li.hover>.arrow{right:auto;top:auto;left:24px;bottom:7px}.sidebar.h-sidebar .nav-list>li.hover.pull_right>.arrow{left:auto;right:24px}.sidebar.h-sidebar .nav-list>li.hover>.arrow:after,.sidebar.h-sidebar .nav-list>li.hover>.arrow:before{border-width:0 8px 8px!important}.sidebar.h-sidebar .nav-list>li.hover>.arrow:after{border-color:transparent;border-left-color:transparent!important;border-right-color:transparent!important;-moz-border-right-colors:none!important;-moz-border-left-colors:none!important;-moz-border-top-colors:none;-moz-border-bottom-colors:none;left:-10px!important;right:auto!important}.sidebar.h-sidebar .nav-list>li.hover>.arrow:before{border-color:transparent;border-left-color:transparent!important;border-right-color:transparent!important;-moz-border-right-colors:none!important;-moz-border-left-colors:none!important;-moz-border-top-colors:none;-moz-border-bottom-colors:none;right:auto!important;left:-10px!important;top:-1px!important}.sidebar.h-sidebar .nav-list>li.hover:hover>a~.arrow{display:none}.sidebar.h-sidebar .nav-list>li.hover:hover>a.dropdown-toggle~.arrow{display:block}.sidebar.h-sidebar .sidebar-shortcuts-large:after,.sidebar.h-sidebar .sidebar-shortcuts-large:before{display:block;content:"";position:absolute;left:50%;margin-left:-8px;border:1px solid transparent;border-width:0 8px 8px}.sidebar.h-sidebar .sidebar-shortcuts-large:after{border-right-color:transparent;-moz-border-right-colors:none;top:-8px}.sidebar.h-sidebar .sidebar-shortcuts-large:before{-moz-border-bottom-colors:#CCC;border-bottom-color:#CCC;top:-9px}.sidebar.h-sidebar .sidebar-toggle{display:none}.sidebar.h-sidebar .sidebar-shortcuts{float:left;display:block;overflow:visible;position:relative;margin:0;padding:12px 8px 9px;max-height:none!important;background-color:transparent}.sidebar.h-sidebar .sidebar-shortcuts:hover .sidebar-shortcuts-large{display:block}.sidebar.h-sidebar .sidebar-shortcuts-large{display:none;width:52px;height:auto;position:absolute;z-index:15;top:100%;margin-top:-5px;left:10px;padding:3px 2px;border:1px solid}.sidebar.h-sidebar .sidebar-shortcuts-mini{width:auto;max-width:52px;display:block;background-color:transparent;padding-top:3px;padding-bottom:5px}.sidebar.h-sidebar .sidebar-shortcuts-mini>.btn{margin:1px;padding:9px!important}.sidebar.h-sidebar .nav-list a .badge,.sidebar.h-sidebar .nav-list a .label{position:absolute;top:11px;right:auto!important;left:50%;margin-left:10px}.sidebar.h-sidebar+.main-content{margin-left:0}.sidebar.h-sidebar+.main-content .breadcrumbs{margin:6px 9px;border:1px solid;border-color:#E5E5E5}.h-sidebar.sidebar-fixed{top:auto;width:100%;left:0;right:0}.h-sidebar.sidebar-fixed:before{z-index:auto}.h-sidebar.sidebar-fixed,.h-sidebar.sidebar-fixed .nav-list{border-right-width:0;border-left-width:0}.h-sidebar.sidebar-fixed .sidebar-shortcuts{border-width:0}.h-sidebar.sidebar-fixed+.main-content{padding-top:88px}}@media only screen and (min-width:992px) and (max-width:991px){.sidebar.h-sidebar+.main-content .breadcrumbs{margin:0;border-width:0 0 1px}}.main-container.container .h-sidebar.sidebar-fixed.navbar-collapse{left:0!important;right:0!important;width:auto!important}@media (min-width:768px){.main-container.container .h-sidebar.sidebar-fixed.navbar-collapse{left:auto!important;right:auto!important;width:744px!important}}@media (min-width:992px){.main-container.container .h-sidebar.sidebar-fixed.navbar-collapse{width:964px!important}}@media (min-width:1200px){.main-container.container .h-sidebar.sidebar-fixed.navbar-collapse{width:1164px!important}}@media (min-width:992px){.sidebar.h-sidebar .nav-list>li>a>.menu-text{background-color:transparent!important;border-width:0!important;-webkit-box-shadow:none!important;box-shadow:none!important;display:inline!important;margin:auto!important;padding:0!important;position:static!important;font-size:inherit;line-height:inherit;text-align:inherit}.sidebar.h-sidebar .nav-list>li>a>.menu-icon{height:auto;font-size:18px}}.main-container .menu-toggler,.sidebar-toggle.sidebar-expand{display:none}@media only screen and (max-width:991px){.sidebar.responsive:before{display:none}.sidebar.responsive{-webkit-box-shadow:2px 1px 2px 0 rgba(0,0,0,.15);box-shadow:2px 1px 2px 0 rgba(0,0,0,.15);z-index:1027;overflow:hidden;max-height:0;-moz-transform:translateX(-200px);-webkit-transform:translateX(-200px);-o-transform:translateX(-200px);-ms-transform:translateX(-200px);transform:translateX(-200px);-webkit-transition:-webkit-transform .2s linear 0s,max-height 0s linear .2s;-moz-transition:-moz-transform .2s linear 0s,max-height 0s linear .2s;-o-transition:-o-transform .2s linear 0s,max-height 0s linear .2s;transition:transform .2s linear 0s,max-height 0s linear .2s;position:relative;bottom:auto;left:190px;margin-left:-190px}}@media (min-width:992px) and (max-width:991px){.sidebar.responsive.compact{-moz-transform:translateX(-115px);-webkit-transform:translateX(-115px);-o-transform:translateX(-115px);-ms-transform:translateX(-115px);transform:translateX(-115px)}.navbar.navbar-fixed-top+.main-container .sidebar.responsive.compact.push_away.display~.footer .footer-inner,.sidebar.responsive.compact.push_away.display+.main-content{-moz-transform:translateX(105px);-webkit-transform:translateX(105px);-o-transform:translateX(105px);-ms-transform:translateX(105px);transform:translateX(105px)}}@media only screen and (max-width:991px){.sidebar.responsive.menu-min{-moz-transform:translateX(-53px);-webkit-transform:translateX(-53px);-o-transform:translateX(-53px);-ms-transform:translateX(-53px);transform:translateX(-53px)}.sidebar.responsive.display{-moz-transform:none!important;-webkit-transform:none!important;-o-transform:none!important;-ms-transform:none!important;transform:none!important;overflow:visible;max-height:2000px;-webkit-transition-delay:0s;-moz-transition-delay:0s;-o-transition-delay:0s;transition-delay:0s}.sidebar.responsive.push_away{-webkit-box-shadow:none!important;box-shadow:none!important}.sidebar.responsive.push_away:before{display:block!important}.sidebar.responsive.push_away+.main-content{-webkit-transition:-webkit-transform .2s linear 0s;-moz-transition:-moz-transform .2s linear 0s;-o-transition:-o-transform .2s linear 0s;transition:transform .2s linear 0s}.sidebar.responsive.push_away.display+.main-content{-moz-transform:translateX(190px);-webkit-transform:translateX(190px);-o-transform:translateX(190px);-ms-transform:translateX(190px);transform:translateX(190px)}.sidebar.responsive.push_away.display.menu-min+.main-content{-moz-transform:translateX(43px);-webkit-transform:translateX(43px);-o-transform:translateX(43px);-ms-transform:translateX(43px);transform:translateX(43px)}.navbar.navbar-fixed-top+.main-container .sidebar.responsive.push_away:before{height:5000px}.navbar.navbar-fixed-top+.main-container .sidebar.responsive.push_away~.footer .footer-inner{-webkit-transition:-webkit-transform .2s linear 0s;-moz-transition:-moz-transform .2s linear 0s;-o-transition:-o-transform .2s linear 0s;transition:transform .2s linear 0s}.navbar.navbar-fixed-top+.main-container .sidebar.responsive.push_away.display~.footer .footer-inner{-moz-transform:translateX(190px);-webkit-transform:translateX(190px);-o-transform:translateX(190px);-ms-transform:translateX(190px);transform:translateX(190px)}.navbar.navbar-fixed-top+.main-container .sidebar.responsive.push_away.display.menu-min~.footer .footer-inner{-moz-transform:translateX(43px);-webkit-transform:translateX(43px);-o-transform:translateX(43px);-ms-transform:translateX(43px);transform:translateX(43px)}.sidebar.responsive .nav-list>li.active:after{height:41px}.sidebar.responsive .nav-list li li.active>a:after{display:none}.sidebar.responsive.menu-min .nav-list>li.active:after{display:block}.sidebar.responsive+.main-content{margin-left:0!important}}@media only screen and (min-width:768px) and (max-width:991px){.main-container.container .sidebar.responsive{-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none;display:none}.main-container.container .sidebar.responsive.display{display:block}.main-container.container .sidebar.responsive.push_away+.main-content,.main-container.container .sidebar.responsive.push_away~.footer .footer-inner{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;transition:none!important;-moz-transform:none!important;-webkit-transform:none!important;-o-transform:none!important;-ms-transform:none!important;transform:none!important}}@media only screen and (max-width:991px){.responsive.sidebar-fixed{position:fixed}.main-container .menu-toggler.fixed{position:fixed;left:auto;z-index:1026;-moz-backface-visibility:hidden}}@media only screen and (max-width:991px){.menu-toggler+.sidebar.responsive{margin-top:40px}.main-container .menu-toggler{display:block;position:absolute;z-index:1026;width:52px;height:32px;margin-right:2px;line-height:normal;padding-left:33px;padding-top:7px;padding-bottom:1px;font-size:13px;font-weight:700;text-transform:uppercase;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.main-container .menu-toggler:hover{text-decoration:none}.main-container .menu-toggler:focus{outline:0}.main-container .menu-toggler:before{border-top:1px solid #87b87f;border-bottom:1px solid #6fb3e0;height:2px;width:24px;content:"";position:absolute;z-index:1;top:13px;left:4px;-webkit-transition:all .1s ease;transition:all .1s ease;-o-transition:none;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.main-container .menu-toggler:after{border-top:1px solid #ffa24d;border-bottom:1px solid #d15b47;content:"";height:2px;width:24px;position:absolute;top:19px;left:4px;-webkit-transition:all .1s ease;transition:all .1s ease;-o-transition:none;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.main-container .menu-toggler.display:before{height:4px;top:8px;border-width:2px}.main-container .menu-toggler.display:after{height:4px;top:20px;border-width:2px}.main-container .menu-toggler>.toggler-text{display:block;position:absolute;bottom:-9px;left:0;border:1px solid transparent;border-width:9px 42px 0;border-top-color:#444;-moz-border-top-colors:#444}.main-container .menu-toggler>.toggler-text:after{display:block;content:"MENU";color:#fff;position:absolute;left:-8px;top:-41px}.menu-toggler+.responsive.sidebar-scroll .nav-wrap{overflow:hidden}}@media only screen and (max-width:320px){.main-container .menu-toggler{width:0}.main-container .menu-toggler>.toggler-text{border-width:7px 16px;bottom:-14px}.main-container .menu-toggler>.toggler-text:after{font-size:9px;font-weight:400;color:#FFF;position:absolute;left:-13px;top:-42px}.main-container .menu-toggler:after,.main-container .menu-toggler:before{margin-top:8px}.main-container .menu-toggler.display:after,.main-container .menu-toggler.display:before{height:2px;border-width:1px}.main-container .menu-toggler.display:before{top:13px}.main-container .menu-toggler.display:after{top:19px}}@media (max-width:991px){.menu-toggler.invisible{position:fixed;z-index:-999;visibility:hidden;opacity:0;width:1px;height:1px}.sidebar.responsive-min,.sidebar.responsive-min.compact,.sidebar.responsive-min.navbar-collapse{width:43px}.sidebar.responsive-min+.main-content{margin-left:43px}.sidebar.responsive-min .nav-list a .badge,.sidebar.responsive-min .nav-list a .label{position:relative;top:-1px;right:auto;left:4px}.sidebar.responsive-min .nav-list .submenu .submenu a .badge,.sidebar.responsive-min .nav-list .submenu .submenu a .label{top:0}.sidebar.responsive-min .nav-list>li>a{position:relative;height:39px;line-height:37px;padding:0}.sidebar.responsive-min .nav-list>li>a>.menu-icon{font-size:18px;height:auto;line-height:inherit;display:inline-block;vertical-align:sub;margin-right:0;width:44px}.sidebar.responsive-min .nav-list>li>a>.menu-text{display:none;text-align:left;position:absolute;top:-1px;left:42px;z-index:1025;width:176px;height:41px;line-height:38px;padding-left:12px;border:1px solid}.sidebar.responsive-min .nav-list>li>a.dropdown-toggle>.menu-text{top:-1px;border-width:1px 1px 0}.sidebar.responsive-min .nav-list>li>a .arrow{display:none}.sidebar.responsive-min .nav-list>li:hover>a>.menu-text{display:block}.sidebar.responsive-min .nav-list>li.active>a:after{border-width:10px 6px;top:8px}.sidebar.responsive-min .nav-list>li.active.open>a:after{display:block}.sidebar.responsive-min .nav-list>li.active.open li.active>a:after{display:none}.sidebar.responsive-min .nav-list>li>.submenu{position:absolute;z-index:1028;left:42px;top:-1px;margin-top:40px;padding-bottom:2px;width:176px;display:none!important}.sidebar.responsive-min .nav-list>li>.submenu:before{display:none}.sidebar.responsive-min .nav-list>li>.submenu:after{content:"";display:block;height:1px;width:1px;position:absolute;right:-1px;top:-1px;border-right:1px solid;border-right-color:inherit}.sidebar.responsive-min .nav-list>li>.submenu li:before{display:none}.sidebar.responsive-min .nav-list>li>.submenu li>a{margin-left:0;padding-left:22px}.sidebar.responsive-min .nav-list>li>.submenu li>a>.menu-icon{left:4px}.sidebar.responsive-min .nav-list>li.hover>.submenu{padding-bottom:0}.sidebar.responsive-min .nav-list>li.open>.submenu{display:none}.sidebar.responsive-min .nav-list>li:hover>.submenu{display:block!important}.sidebar.responsive-min .nav-list>li>.arrow{top:10px}.sidebar.responsive-min .nav-list>li>.arrow:after,.sidebar.responsive-min .nav-list>li>.arrow:before{border-width:8px;left:-16px}.sidebar.responsive-min .nav-list>li>.arrow:before{left:-17px}.sidebar.responsive-min .nav-list li>.arrow{right:-1px}.sidebar.responsive-min .nav-list>li:hover>.arrow{display:block}.sidebar.responsive-min .nav-list>li.pull_up>.arrow{z-index:1029}.sidebar.responsive-min .nav-list>li.pull_up>.arrow:after,.sidebar.responsive-min .nav-list>li.pull_up>.arrow:before{border-width:10px;left:-20px}.sidebar.responsive-min .nav-list>li.pull_up>.arrow:before{left:-21px}.sidebar.responsive-min .sidebar-shortcuts{position:relative;overflow:visible;z-index:1}.sidebar.responsive-min .sidebar-shortcuts-mini{display:block}.sidebar.responsive-min .sidebar-shortcuts-large{display:none;position:absolute;top:0;left:42px;width:182px;padding:0 2px 3px;border:1px solid;border-top-width:0}.sidebar.responsive-min .sidebar-shortcuts:hover .sidebar-shortcuts-large{display:block}.sidebar.responsive-min .sidebar-toggle:before{left:5px;right:5px}.sidebar.responsive-min .sidebar-toggle>.ace-icon{font-size:13px;padding:0 4px;line-height:15px;border-width:1px}.sidebar.responsive-min .nav-list>li>.submenu li>.submenu>li>a{margin-left:2px!important;padding-left:30px}.sidebar.responsive-min .nav-list>li>.submenu li>.submenu>li>.submenu>li>a{margin-left:2px!important;padding-left:45px}.sidebar.responsive-min .nav-list li.active.open>.submenu>li.active>a:after,.sidebar.responsive-min .nav-list>li.active.open:hover>a:after,.sidebar.responsive-min .nav-list>li.active:hover:after,.sidebar.responsive-min .nav-list>li.active:hover>a:after,.sidebar.responsive-min .nav-list>li>.submenu li.active>a:after{display:none}.sidebar.responsive-min:before{display:block}.sidebar.responsive-min .sidebar-toggle.sidebar-collapse{display:none}.sidebar.responsive-min .sidebar-toggle.sidebar-expand{display:block}.sidebar.responsive-min+.main-content{margin-left:43px!important}.sidebar.responsive-min+.main-content .breadcrumb{margin-left:12px}.sidebar.responsive-max{display:block;position:relative;left:190px;margin-left:-190px;z-index:1027}.sidebar.responsive-max .sidebar-toggle.sidebar-collapse{display:none}.sidebar.responsive-max .sidebar-toggle.sidebar-expand{display:block}.sidebar.responsive-max+.main-content{margin-left:43px!important}.sidebar.responsive-max+.main-content .breadcrumb{margin-left:12px}}@media (max-width:991px) and only screen and (min-width:992px){.sidebar.responsive-min .nav-list li.hover>.submenu{margin-left:0}.sidebar.responsive-min .nav-list>li>.submenu li.hover>.submenu>li>a,.sidebar.responsive-min .nav-list>li>.submenu li>.submenu>li.hover>.submenu>li>a{margin-left:0!important}}@media (max-width:991px) and (min-width:992px){.sidebar.responsive-min.compact .nav-list>li>a{height:39px;line-height:37px;padding:0 16px 0 7px;position:relative}.sidebar.responsive-min.compact .nav-list>li>a>.menu-icon{font-size:18px;height:auto;line-height:inherit;display:inline-block;vertical-align:sub;width:auto}}@media only screen and (min-width:992px){.sidebar.navbar-collapse{max-height:none}}@media only screen and (max-width:991px){.sidebar.navbar-collapse{position:relative;float:none!important;margin-top:auto;z-index:1;width:100%!important;max-height:340px;margin-left:0;margin-right:0}.sidebar.navbar-collapse:before{display:none}.sidebar.navbar-collapse .nav-list>li:last-child{border-bottom-width:0}.sidebar.navbar-collapse .nav-list>li>a{padding-top:10px!important;padding-bottom:10px!important;line-height:20px!important;height:41px!important}.sidebar.navbar-collapse .nav-list>li:before{height:43px!important}.sidebar.navbar-collapse li>.arrow{display:none!important}.sidebar.navbar-collapse .nav-list li>.submenu{border-left-width:0!important}.sidebar.navbar-collapse .sidebar-toggle{display:none!important}.sidebar.navbar-collapse .sidebar-shortcuts{padding:3px 0 6px!important;max-height:none!important;border-bottom-width:0}.sidebar.navbar-collapse+.main-content{margin-left:0!important}.sidebar.navbar-collapse+.main-content .breadcrumb{margin-left:12px}.sidebar.navbar-collapse .nav-wrap+.ace-scroll{display:none}.sidebar.navbar-collapse.menu-min .nav-list>li>.submenu{position:relative;left:auto;top:auto;width:auto;z-index:auto;margin-top:auto!important;padding-top:0;padding-bottom:0;border-width:1px 0 0;-webkit-box-shadow:none!important;box-shadow:none!important}.sidebar.navbar-collapse.menu-min .nav-list>li>.submenu:before,.sidebar.navbar-collapse.menu-min .nav-list>li>.submenu>li:before{display:block}.sidebar.navbar-collapse.menu-min .nav-list>li>.submenu li>a{padding-left:37px!important}.sidebar.navbar-collapse.menu-min .nav-list>li>.submenu li>a>.menu-icon{left:10px}.sidebar.navbar-collapse.menu-min .nav-list>li>.submenu:after{display:none}.sidebar.navbar-collapse.menu-min .nav-list>li>a:hover:before{width:3px}.sidebar.navbar-collapse.menu-min .nav-list>li>a{text-align:left;padding-left:7px}.sidebar.navbar-collapse.menu-min .nav-list>li>a>.menu-icon{display:inline-block;width:auto;margin-right:2px}.sidebar.navbar-collapse.menu-min .nav-list>li>a>.menu-text{position:relative;display:inline!important;line-height:normal;padding-left:0;height:auto;top:auto;left:auto;z-index:auto;width:auto;border-width:0!important;background-color:transparent!important;-webkit-box-shadow:none!important;box-shadow:none!important}.sidebar.navbar-collapse.menu-min .nav-list a>.arrow{display:block}.sidebar.navbar-collapse.menu-min .nav-list>li:hover>.submenu{display:none!important}.sidebar.navbar-collapse.menu-min .nav-list>li.active>.submenu,.sidebar.navbar-collapse.menu-min .nav-list>li>.submenu.nav-show{display:block!important}.sidebar.navbar-collapse.menu-min .nav-list>li>.submenu.nav-hide{display:none!important}.sidebar.navbar-collapse.menu-min .sidebar-shortcuts-large{display:block;position:static;-webkit-box-shadow:none!important;box-shadow:none!important;border-width:0;background-color:transparent;width:auto;padding:0!important}.sidebar.navbar-collapse.menu-min .sidebar-shortcuts-mini{display:none}.sidebar.navbar-collapse .nav-list a .badge,.sidebar.navbar-collapse .nav-list a .label{position:relative;top:-1px;right:auto;left:4px}.sidebar.navbar-collapse .nav-list li.active>a:after,.sidebar.navbar-collapse .nav-list li.active>a:before,.sidebar.navbar-collapse .nav-list>li.active:after,.sidebar.navbar-collapse .nav-list>li.highlight.active>a:after,.sidebar.navbar-collapse .nav-list>li.highlight.active>a:before{display:none!important}}@media (min-width:992px) and (max-width:991px){.sidebar.navbar-collapse .nav-list>li>.submenu li.hover>.submenu>li>a,.sidebar.navbar-collapse .nav-list>li>.submenu li>.submenu>li.hover>.submenu>li>a{margin-left:20px!important}}@media (max-width:991px){.navbar-fixed-top+.main-container .sidebar.navbar-collapse{position:fixed;z-index:1027}}@media (min-width:768px) and (max-width:991px){.navbar-fixed-top+.main-container.container .sidebar.navbar-collapse{width:744px!important}}.sidebar-scroll .sidebar-shortcuts{min-height:41px;border-bottom:1px solid}.sidebar-scroll .sidebar-toggle{border-top:1px solid}.sidebar-scroll .nav-list>li:first-child{border-top-width:0}.sidebar-scroll .nav-list>li:last-child{border-bottom-width:0}.sidebar-scroll .nav-wrap .sidebar-shortcuts{min-height:40px;border-bottom-width:0}.sidebar-scroll .nav-wrap .sidebar-shortcuts+.nav-list>li:first-child{border-top-width:1px}.sidebar-scroll .nav-wrap-t .sidebar-toggle{border-top-width:0}.sidebar-scroll .nav-wrap-t .nav-list>li:last-child{border-bottom-width:1px}.sidebar .nav-wrap+.ace-scroll{position:absolute;right:0;top:0;z-index:1}.sidebar .nav-wrap+.scrollout{right:-8px}@media only screen and (min--moz-device-pixel-ratio:0){.navbar.navbar-fixed-top{border-radius:.05em}.navbar.navbar-fixed-top,.navbar.navbar-fixed-top .ace-nav>li .dropdown-menu,.navbar.navbar-fixed-top>.navbar-container,.sidebar.sidebar-fixed{-moz-backface-visibility:hidden}}.ace-scroll{overflow:hidden}.scroll-content{position:static;overflow:hidden}.scroll-track{position:absolute;top:auto;bottom:auto;right:0;height:auto;background-color:#E7E7E7;z-index:99;width:0;opacity:0}.scroll-bar{position:absolute;top:0;left:0;width:inherit;background:#bbd4e5}.scroll-hz .scroll-track{top:auto;left:auto;right:auto;bottom:0;height:8px;width:auto}.scroll-hz .scroll-bar{height:inherit;width:auto}.scroll-active .scroll-track{-webkit-transition:all .25s ease .6s;-o-transition:all .25s ease .6s;transition:all .25s ease .6s}.scroll-active .scroll-track.active,.scroll-active .scroll-track:active,.scroll-active:hover .scroll-track{width:8px;opacity:1;-webkit-transition-duration:.15s;transition-duration:.15s;-webkit-transition-delay:0s;transition-delay:0s}.scroll-track.active>.scroll-bar{transition-property:none!important;transition-duration:0s!important}.scroll-margin .scroll-track{right:1px}.scroll-left .scroll-track{right:auto;left:0}.scroll-margin.scroll-left .scroll-track{left:1px}.scroll-top .scroll-track{bottom:auto;top:0}.scroll-margin.scroll-top .scroll-track{top:1px}.scroll-dark .scroll-bar{background-color:rgba(0,0,0,.25)}.scroll-dark .scroll-track{background-color:rgba(0,0,0,.15)}.scroll-light .scroll-bar{background-color:rgba(0,0,0,.14)}.scroll-light .scroll-track{background-color:rgba(0,0,0,.07)}.no-track .scroll-track{background-color:transparent}.scroll-visible .scroll-track{opacity:1;width:8px}.scroll-visible.scroll-hz .scroll-track{height:8px;width:auto}.scroll-thin .scroll-track.active,.scroll-thin .scroll-track:active,.scroll-thin.scroll-visible .scroll-track,.scroll-thin:hover .scroll-track{width:6px}.scroll-thin.scroll-hz .scroll-track.active,.scroll-thin.scroll-hz .scroll-track:active,.scroll-thin.scroll-hz.scroll-visible .scroll-track,.scroll-thin.scroll-hz:hover .scroll-track{width:auto;height:6px}.scroll-chrome .scroll-bar{background-color:transparent;width:11px}.scroll-chrome .scroll-bar:before{display:block;content:"";position:absolute;top:1px;bottom:3px;left:1px;right:1px;background-color:#D9D9D9;border:1px solid #BBB;border-radius:1px}.scroll-chrome .scroll-track{width:12px!important;background-color:#F2F2F2;border:1px solid;border-width:1px 0 1px 1px;border-color:#E6E6E6 transparent #E6E6E6 #DBDBDB}.scroll-chrome .scroll-track:hover .scroll-bar:before{background-color:silver;border-color:#A6A6A6}.scroll-chrome .scroll-track.active .scroll-bar:before{background-color:#A9A9A9;border-color:#8B8B8B}.nav-wrap+.scroll-active .scroll-track{width:8px}.nav-scroll.scroll-active .scroll-track{width:8px;right:0}.nav-scroll.scroll-active:hover .scroll-track,.nav-wrap:hover+.scroll-active .scroll-track{width:8px;opacity:1;-webkit-transition-duration:.15s;transition-duration:.15s;-webkit-transition-delay:0s;transition-delay:0s}.nav-scroll.scroll-active:hover .scroll-track{width:8px}.nav-scroll.ace-scroll,.nav-scroll.ace-scroll .scroll-content{overflow:visible}.nav-scroll.ace-scroll.scroll-active,.nav-scroll.ace-scroll.scroll-active .scroll-content{overflow:hidden}.breadcrumbs{position:relative;z-index:auto;border-bottom:1px solid #e5e5e5;background-color:#f5f5f5;min-height:41px;line-height:40px;padding:0 12px 0 0}.breadcrumb{background-color:transparent;display:inline-block;line-height:20px;margin:6px 22px 0 12px;padding:0;font-size:13px;color:#333;border-radius:0}.breadcrumb>li,.breadcrumb>li.active{color:#555;padding:0 3px}.breadcrumb>li>a{display:inline-block;color:#4c8fbd}.breadcrumb>li+li:before{font-family:FontAwesome;font-size:14px;content:"\f105";color:#b2b6bf;padding:0;margin:0 8px 0 0;position:relative;top:1px}.breadcrumb .home-icon{font-size:20px;margin-left:2px;margin-right:2px;vertical-align:top}@media only screen and (max-width:480px){.breadcrumb>li>a{padding:0 1px}}@media only screen and (max-width:991px){.menu-toggler+.sidebar.responsive+.main-content .breadcrumb{margin-left:90px}}@media only screen and (max-width:320px){.breadcrumb{margin-left:8px}.menu-toggler+.sidebar.responsive+.main-content .breadcrumb{margin-left:36px}}@media (min-width:992px){.breadcrumbs-fixed{position:fixed;right:0;left:0;top:auto;z-index:1024}.breadcrumbs-fixed+.page-content{padding-top:49px}.sidebar+.main-content .breadcrumbs-fixed{left:190px}body.mob-safari .breadcrumbs-fixed{top:45px}}@media (min-width:992px){.sidebar.compact+.main-content .breadcrumbs-fixed{left:105px}}@media (min-width:992px){.sidebar.menu-min+.main-content .breadcrumbs-fixed{left:43px}}@media (min-width:992px) and (max-width:991px){.breadcrumbs-fixed,.sidebar.menu-min+.main-content .breadcrumbs-fixed{left:0}.sidebar.responsive-max+.main-content .breadcrumbs-fixed,.sidebar.responsive-min+.main-content .breadcrumbs-fixed{left:43px}}@media (min-width:992px){.container.main-container .sidebar.compact+.main-content .breadcrumbs-fixed{left:auto;right:auto;width:639px}}@media (min-width:992px){.container.main-container .breadcrumbs-fixed{left:auto;right:auto;width:744px}.container.main-container .sidebar+.main-content .breadcrumbs-fixed{left:auto;right:auto;width:554px}.container.main-container .sidebar.menu-min+.main-content .breadcrumbs-fixed{left:auto;right:auto;width:701px}}@media (min-width:992px){.container.main-container .sidebar.compact+.main-content .breadcrumbs-fixed{width:859px}}@media (min-width:992px){.container.main-container .breadcrumbs-fixed{width:964px}.container.main-container .sidebar+.main-content .breadcrumbs-fixed{width:774px}.container.main-container .sidebar.menu-min+.main-content .breadcrumbs-fixed{width:921px}}@media (min-width:992px){.container.main-container .sidebar.compact+.main-content .breadcrumbs-fixed{width:1059px}}@media (min-width:1200px){.container.main-container .breadcrumbs-fixed{width:1164px}.container.main-container .sidebar+.main-content .breadcrumbs-fixed{width:974px}.container.main-container .sidebar.menu-min+.main-content .breadcrumbs-fixed{width:1121px}}@media (min-width:992px) and (max-width:991px){.container.main-container .sidebar.compact+.main-content .breadcrumbs-fixed{width:744px}}@media (min-width:992px) and (max-width:991px){.container.main-container .breadcrumbs-fixed,.container.main-container .sidebar.menu-min+.main-content .breadcrumbs-fixed{width:744px}.container.main-container .sidebar.responsive-max+.main-content .breadcrumbs-fixed,.container.main-container .sidebar.responsive-min+.main-content .breadcrumbs-fixed{left:auto;right:auto;width:701px}}@media (min-width:992px){.h-sidebar+.main-content .breadcrumbs.breadcrumbs-fixed{position:relative!important;top:auto;left:auto;z-index:auto;width:auto!important}.h-sidebar+.main-content .page-content{padding-top:8px!important}}.nav-search{position:absolute;right:22px;line-height:24px}.breadcrumbs .nav-search{top:6px}.nav-search .form-search{margin-bottom:0}.nav-search .nav-search-input{border:1px solid #6fb3e0;width:152px;height:28px!important;padding-top:2px;padding-bottom:2px;border-radius:4px!important;font-size:13px;line-height:1.3;color:#666!important;z-index:11;-webkit-transition:width ease .15s;-o-transition:width ease .15s;transition:width ease .15s}.nav-search .nav-search-input+.dropdown-menu{min-width:0;left:0;right:0}.nav-search .nav-search-input:focus,.nav-search .nav-search-input:hover{border-color:#6fb3e0}.nav-search .nav-search-icon{color:#6fb3e0!important;font-size:14px!important;line-height:24px!important;background-color:transparent}.nav-search.minimized .nav-search-input{width:0;opacity:0;filter:alpha(opacity=0);max-width:0}.nav-search.minimized .nav-search-btn:active+.nav-search-input,.nav-search.minimized .nav-search-input:active,.nav-search.minimized .nav-search-input:focus,.nav-search.minimized .nav-search-input:hover,.nav-search.minimized:hover .nav-search-input{opacity:1;filter:alpha(opacity=100);width:152px;max-width:152px}.nav-search.minimized .nav-search-icon{border:1px solid;border-radius:100%;background-color:#FFF;padding:0 5px!important}.nav-search-icon,.nav-search.minimized .nav-search-input:active~.nav-search-icon,.nav-search.minimized .nav-search-input:focus~.nav-search-icon,.nav-search.minimized .nav-search-input:hover~.nav-search-icon,.nav-search.minimized:hover .nav-search-icon{border:none;border-radius:0;padding:0 3px!important}.sidebar>.nav-search{position:static;background-color:#FAFAFA;border-bottom:1px solid #DDD;text-align:center;height:35px;padding-top:6px}.sidebar>.nav-search .nav-search-input{width:162px!important;border-radius:0!important;max-width:162px!important;opacity:1!important;filter:alpha(opacity=100)!important}.sidebar>.nav-search .nav-search-input+.dropdown-menu{text-align:left}.sidebar.menu-min .nav-search .form-search{position:absolute;left:5px;z-index:14}.sidebar.menu-min .nav-search .nav-search-input{width:0!important;max-width:0!important;opacity:0!important;filter:alpha(opacity=0)!important}.sidebar.menu-min .nav-search .nav-search-input:active,.sidebar.menu-min .nav-search .nav-search-input:focus,.sidebar.menu-min .nav-search .nav-search-input:hover{width:162px!important;max-width:162px!important;opacity:1!important;filter:alpha(opacity=100)!important}.sidebar.menu-min .nav-search .nav-search-input:active~#nav-search-icon,.sidebar.menu-min .nav-search .nav-search-input:focus~#nav-search-icon,.sidebar.menu-min .nav-search .nav-search-input:hover~#nav-search-icon{border:none;border-radius:0;padding:0 3px!important}.sidebar.menu-min .nav-search:hover .nav-search-input{width:162px!important;max-width:162px!important;opacity:1!important;filter:alpha(opacity=100)!important}.sidebar.menu-min .nav-search:hover .nav-search-input~.nav-search-icon{border:none;border-radius:0;padding:0 3px!important}.sidebar.menu-min .nav-search .nav-search-icon{border:1px solid;border-radius:32px;background-color:#FFF;padding:0 5px!important}@media (max-width:991px){.sidebar.responsive-min .nav-search .form-search{position:absolute;left:5px;z-index:14}.sidebar.responsive-min .nav-search .nav-search-input{width:0!important;max-width:0!important;opacity:0!important;filter:alpha(opacity=0)!important}.sidebar.responsive-min .nav-search .nav-search-input:active,.sidebar.responsive-min .nav-search .nav-search-input:focus,.sidebar.responsive-min .nav-search .nav-search-input:hover{width:162px!important;max-width:162px!important;opacity:1!important;filter:alpha(opacity=100)!important}.sidebar.responsive-min .nav-search .nav-search-input:active~#nav-search-icon,.sidebar.responsive-min .nav-search .nav-search-input:focus~#nav-search-icon,.sidebar.responsive-min .nav-search .nav-search-input:hover~#nav-search-icon{border:none;border-radius:0;padding:0 3px!important}.sidebar.responsive-min .nav-search:hover .nav-search-input{width:162px!important;max-width:162px!important;opacity:1!important;filter:alpha(opacity=100)!important}.sidebar.responsive-min .nav-search:hover .nav-search-input~.nav-search-icon{border:none;border-radius:0;padding:0 3px!important}.sidebar.responsive-min .nav-search .nav-search-icon{border:1px solid;border-radius:32px;background-color:#FFF;padding:0 5px!important}}@media only screen and (max-width:991px){.nav-search{right:10px}.nav-search .nav-search-input{width:105px}.nav-search .nav-search-btn:active+.nav-search-input,.nav-search .nav-search-input:active,.nav-search .nav-search-input:focus,.nav-search .nav-search-input:hover,.nav-search:hover .nav-search-input{width:145px}}@media only screen and (max-width:767px){.nav-search .nav-search-input{width:0;opacity:0;filter:alpha(opacity=0);max-width:0}.nav-search .nav-search-btn:active+.nav-search-input,.nav-search .nav-search-input:active,.nav-search .nav-search-input:focus,.nav-search .nav-search-input:hover,.nav-search:hover .nav-search-input{opacity:1;filter:alpha(opacity=100);width:152px;max-width:152px}.nav-search .nav-search-icon{border:1px solid;border-radius:100%;background-color:#FFF;padding:0 5px!important}.nav-search .nav-search-input:active~.nav-search-icon,.nav-search .nav-search-input:focus~.nav-search-icon,.nav-search .nav-search-input:hover~.nav-search-icon,.nav-search:hover .nav-search-icon{border:none;border-radius:0;padding:0 3px!important}}.footer{padding-top:75px;height:0;width:0}.footer .footer-inner{text-align:center;position:absolute;z-index:auto;left:0;right:0;bottom:0}.sidebar~.footer .footer-inner{left:190px}@media (min-width:992px){.sidebar.compact~.footer .footer-inner{left:105px}}.sidebar.menu-min~.footer .footer-inner{left:43px}@media (min-width:992px){.sidebar.h-sidebar~.footer .footer-inner{left:0}}@media (max-width:991px){.footer .footer-inner,.sidebar.compact~.footer .footer-inner,.sidebar.menu-min~.footer .footer-inner,.sidebar~.footer .footer-inner{left:0}.sidebar.responsive-min~.footer .footer-inner{left:43px}}@media (min-width:768px) and (max-width:991px){.container.main-container .footer .footer-inner{left:auto!important;right:auto!important;margin-left:auto;width:744px}}@media (min-width:992px){.container.main-container .footer .footer-inner{left:auto!important;right:auto!important;width:964px}}@media (min-width:1200px){.container.main-container .footer .footer-inner{width:1164px}}@media (min-width:768px) and (max-width:991px){.container.main-container .sidebar~.footer .footer-inner{left:auto!important;right:auto!important;margin-left:auto;width:744px}}@media (min-width:992px){.container.main-container .sidebar~.footer .footer-inner{left:auto!important;right:auto!important;margin-left:190px;width:774px}}@media (min-width:1200px){.container.main-container .sidebar~.footer .footer-inner{margin-left:190px;width:974px}}@media (min-width:992px){.container.main-container .sidebar.compact~.footer .footer-inner{margin-left:105px;width:859px}}@media (min-width:1200px){.container.main-container .sidebar.compact~.footer .footer-inner{margin-left:105px;width:1059px}}@media (min-width:992px){.container.main-container .sidebar.menu-min~.footer .footer-inner{margin-left:43px;width:921px}}@media (min-width:1200px){.container.main-container .sidebar.menu-min~.footer .footer-inner{margin-left:43px;width:1121px}}@media (min-width:992px){.container.main-container .sidebar.h-sidebar~.footer .footer-inner{margin-left:0;width:964px}}@media (min-width:992px){.container.main-container .sidebar.h-sidebar~.footer .footer-inner{margin-left:0;width:964px}}@media (min-width:1200px){.container.main-container .sidebar.h-sidebar~.footer .footer-inner{margin-left:0;width:1164px}}@media (min-width:768px) and (max-width:991px){.container.main-container .sidebar.responsive-min~.footer .footer-inner{margin-left:43px;width:701px}}.footer .footer-inner .footer-content{position:absolute;left:12px;right:12px;bottom:4px;padding:8px;line-height:36px;border-top:3px double #E5E5E5}.footer.footer-fixed .footer-inner{position:fixed;z-index:999;bottom:0}.footer.footer-fixed .footer-inner .footer-content{left:2px;right:2px;bottom:2px;border:1px solid #DDD;background-color:#F2F2F2}.footer.footer-fixed+.btn-scroll-up{z-index:999}.btn{display:inline-block;color:#FFF!important;text-shadow:0 -1px 0 rgba(0,0,0,.25)!important;background-image:none!important;border:5px solid #FFF;border-radius:0;box-shadow:none!important;-webkit-transition:all ease .15s;-o-transition:all ease .15s;transition:all ease .15s;cursor:pointer;vertical-align:middle;margin:0;position:relative}.btn-lg{border-width:5px;line-height:1.35;padding:7px 16px}.btn-sm{border-width:4px;font-size:13px;padding:4px 9px;line-height:1.39}.btn-xs{border-width:3px}.btn-minier{padding:0 4px;line-height:18px;border-width:2px;font-size:12px}button.btn:active{top:1px}.btn,.btn-default,.btn-default:focus,.btn:focus{background-color:#abbac3!important;border-color:#abbac3}.btn-default:active,.btn-default:hover,.btn:active,.btn:hover,.open .btn-default.dropdown-toggle,.open .btn.dropdown-toggle{background-color:#8b9aa3!important;border-color:#abbac3}.btn-default.no-border:active,.btn-default.no-border:hover,.btn.no-border:active,.btn.no-border:hover{border-color:#8b9aa3}.btn-default.no-hover:active,.btn-default.no-hover:hover,.btn.no-hover:active,.btn.no-hover:hover{background-color:#abbac3!important}.btn-default.active,.btn.active{background-color:#9baab3!important;border-color:#8799a4}.btn-default.no-border.active,.btn.no-border.active{background-color:#92a3ac!important;border-color:#92a3ac}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,.btn.disabled,.btn.disabled.active,.btn.disabled:active,.btn.disabled:focus,.btn.disabled:hover,.btn[disabled],.btn[disabled].active,.btn[disabled]:active,.btn[disabled]:focus,.btn[disabled]:hover,fieldset[disabled] .btn,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover,fieldset[disabled] .btn.active,fieldset[disabled] .btn:active,fieldset[disabled] .btn:focus,fieldset[disabled] .btn:hover{background-color:#abbac3!important;border-color:#abbac3}.btn-primary,.btn-primary:focus{background-color:#428bca!important;border-color:#428bca}.btn-primary:active,.btn-primary:hover,.open .btn-primary.dropdown-toggle{background-color:#1b6aaa!important;border-color:#428bca}.btn-primary.no-border:active,.btn-primary.no-border:hover{border-color:#1b6aaa}.btn-primary.no-hover:active,.btn-primary.no-hover:hover{background-color:#428bca!important}.btn-primary.active{background-color:#2f7bba!important;border-color:#27689d}.btn-primary.no-border.active{background-color:#2b72ae!important;border-color:#2b72ae}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#428bca!important;border-color:#428bca}.btn-info,.btn-info:focus{background-color:#6fb3e0!important;border-color:#6fb3e0}.btn-info:active,.btn-info:hover,.open .btn-info.dropdown-toggle{background-color:#4f99c6!important;border-color:#6fb3e0}.btn-info.no-border:active,.btn-info.no-border:hover{border-color:#4f99c6}.btn-info.no-hover:active,.btn-info.no-hover:hover{background-color:#6fb3e0!important}.btn-info.active{background-color:#5fa6d3!important;border-color:#4396cb}.btn-info.no-border.active{background-color:#539fd0!important;border-color:#539fd0}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#6fb3e0!important;border-color:#6fb3e0}.btn-info2,.btn-info2:focus{background-color:#95c6e5!important;border-color:#95c6e5}.btn-info2:active,.btn-info2:hover,.open .btn-info2.dropdown-toggle{background-color:#67a6ce!important;border-color:#95c6e5}.btn-info2.no-border:active,.btn-info2.no-border:hover{border-color:#67a6ce}.btn-info2.no-hover:active,.btn-info2.no-hover:hover{background-color:#95c6e5!important}.btn-info2.active{background-color:#7eb6da!important;border-color:#62a6d1}.btn-info2.no-border.active{background-color:#72afd6!important;border-color:#72afd6}.btn-info2.disabled,.btn-info2.disabled.active,.btn-info2.disabled:active,.btn-info2.disabled:focus,.btn-info2.disabled:hover,.btn-info2[disabled],.btn-info2[disabled].active,.btn-info2[disabled]:active,.btn-info2[disabled]:focus,.btn-info2[disabled]:hover,fieldset[disabled] .btn-info2,fieldset[disabled] .btn-info2.active,fieldset[disabled] .btn-info2:active,fieldset[disabled] .btn-info2:focus,fieldset[disabled] .btn-info2:hover{background-color:#95c6e5!important;border-color:#95c6e5}.btn-success,.btn-success:focus{background-color:#87b87f!important;border-color:#87b87f}.btn-success:active,.btn-success:hover,.open .btn-success.dropdown-toggle{background-color:#629b58!important;border-color:#87b87f}.btn-success.no-border:active,.btn-success.no-border:hover{border-color:#629b58}.btn-success.no-hover:active,.btn-success.no-hover:hover{background-color:#87b87f!important}.btn-success.active{background-color:#75aa6c!important;border-color:#629959}.btn-success.no-border.active{background-color:#6ba462!important;border-color:#6ba462}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#87b87f!important;border-color:#87b87f}.btn-warning,.btn-warning:focus{background-color:#ffb752!important;border-color:#ffb752}.btn-warning:active,.btn-warning:hover,.open .btn-warning.dropdown-toggle{background-color:#e59729!important;border-color:#ffb752}.btn-warning.no-border:active,.btn-warning.no-border:hover{border-color:#e59729}.btn-warning.no-hover:active,.btn-warning.no-hover:hover{background-color:#ffb752!important}.btn-warning.active{background-color:#f2a73e!important;border-color:#f0981c}.btn-warning.no-border.active{background-color:#f1a02f!important;border-color:#f1a02f}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#ffb752!important;border-color:#ffb752}.btn-danger,.btn-danger:focus{background-color:#d15b47!important;border-color:#d15b47}.btn-danger:active,.btn-danger:hover,.open .btn-danger.dropdown-toggle{background-color:#b74635!important;border-color:#d15b47}.btn-danger.no-border:active,.btn-danger.no-border:hover{border-color:#b74635}.btn-danger.no-hover:active,.btn-danger.no-hover:hover{background-color:#d15b47!important}.btn-danger.active{background-color:#c4513e!important;border-color:#aa4434}.btn-danger.no-border.active{background-color:#ba4b39!important;border-color:#ba4b39}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d15b47!important;border-color:#d15b47}.btn-inverse,.btn-inverse:focus{background-color:#555!important;border-color:#555}.btn-inverse:active,.btn-inverse:hover,.open .btn-inverse.dropdown-toggle{background-color:#303030!important;border-color:#555}.btn-inverse.no-border:active,.btn-inverse.no-border:hover{border-color:#303030}.btn-inverse.no-hover:active,.btn-inverse.no-hover:hover{background-color:#555!important}.btn-inverse.active{background-color:#434343!important;border-color:#313131}.btn-inverse.no-border.active{background-color:#3b3b3b!important;border-color:#3b3b3b}.btn-inverse.disabled,.btn-inverse.disabled.active,.btn-inverse.disabled:active,.btn-inverse.disabled:focus,.btn-inverse.disabled:hover,.btn-inverse[disabled],.btn-inverse[disabled].active,.btn-inverse[disabled]:active,.btn-inverse[disabled]:focus,.btn-inverse[disabled]:hover,fieldset[disabled] .btn-inverse,fieldset[disabled] .btn-inverse.active,fieldset[disabled] .btn-inverse:active,fieldset[disabled] .btn-inverse:focus,fieldset[disabled] .btn-inverse:hover{background-color:#555!important;border-color:#555}.btn-pink,.btn-pink:focus{background-color:#d6487e!important;border-color:#d6487e}.btn-pink:active,.btn-pink:hover,.open .btn-pink.dropdown-toggle{background-color:#b73766!important;border-color:#d6487e}.btn-pink.no-border:active,.btn-pink.no-border:hover{border-color:#b73766}.btn-pink.no-hover:active,.btn-pink.no-hover:hover{background-color:#d6487e!important}.btn-pink.active{background-color:#c74072!important;border-color:#af3462}.btn-pink.no-border.active{background-color:#be386a!important;border-color:#be386a}.btn-pink.disabled,.btn-pink.disabled.active,.btn-pink.disabled:active,.btn-pink.disabled:focus,.btn-pink.disabled:hover,.btn-pink[disabled],.btn-pink[disabled].active,.btn-pink[disabled]:active,.btn-pink[disabled]:focus,.btn-pink[disabled]:hover,fieldset[disabled] .btn-pink,fieldset[disabled] .btn-pink.active,fieldset[disabled] .btn-pink:active,fieldset[disabled] .btn-pink:focus,fieldset[disabled] .btn-pink:hover{background-color:#d6487e!important;border-color:#d6487e}.btn-purple,.btn-purple:focus{background-color:#9585bf!important;border-color:#9585bf}.btn-purple:active,.btn-purple:hover,.open .btn-purple.dropdown-toggle{background-color:#7461aa!important;border-color:#9585bf}.btn-purple.no-border:active,.btn-purple.no-border:hover{border-color:#7461aa}.btn-purple.no-hover:active,.btn-purple.no-hover:hover{background-color:#9585bf!important}.btn-purple.active{background-color:#8573b5!important;border-color:#705ca8}.btn-purple.no-border.active{background-color:#7c69af!important;border-color:#7c69af}.btn-purple.disabled,.btn-purple.disabled.active,.btn-purple.disabled:active,.btn-purple.disabled:focus,.btn-purple.disabled:hover,.btn-purple[disabled],.btn-purple[disabled].active,.btn-purple[disabled]:active,.btn-purple[disabled]:focus,.btn-purple[disabled]:hover,fieldset[disabled] .btn-purple,fieldset[disabled] .btn-purple.active,fieldset[disabled] .btn-purple:active,fieldset[disabled] .btn-purple:focus,fieldset[disabled] .btn-purple:hover{background-color:#9585bf!important;border-color:#9585bf}.btn-grey,.btn-grey:focus{background-color:#a0a0a0!important;border-color:#a0a0a0}.btn-grey:active,.btn-grey:hover,.open .btn-grey.dropdown-toggle{background-color:#888!important;border-color:#a0a0a0}.btn-grey.no-border:active,.btn-grey.no-border:hover{border-color:#888}.btn-grey.no-hover:active,.btn-grey.no-hover:hover{background-color:#a0a0a0!important}.btn-grey.active{background-color:#949494!important;border-color:#828282}.btn-grey.no-border.active{background-color:#8c8c8c!important;border-color:#8c8c8c}.btn-grey.disabled,.btn-grey.disabled.active,.btn-grey.disabled:active,.btn-grey.disabled:focus,.btn-grey.disabled:hover,.btn-grey[disabled],.btn-grey[disabled].active,.btn-grey[disabled]:active,.btn-grey[disabled]:focus,.btn-grey[disabled]:hover,fieldset[disabled] .btn-grey,fieldset[disabled] .btn-grey.active,fieldset[disabled] .btn-grey:active,fieldset[disabled] .btn-grey:focus,fieldset[disabled] .btn-grey:hover{background-color:#a0a0a0!important;border-color:#a0a0a0}.btn-yellow{color:#963!important;text-shadow:0 -1px 0 rgba(255,255,255,.4)!important}.btn-yellow,.btn-yellow:focus{background-color:#fee188!important;border-color:#fee188}.btn-yellow:active,.btn-yellow:hover,.open .btn-yellow.dropdown-toggle{background-color:#f7d05b!important;border-color:#fee188}.btn-yellow.no-border:active,.btn-yellow.no-border:hover{border-color:#f7d05b}.btn-yellow.no-hover:active,.btn-yellow.no-hover:hover{background-color:#fee188!important}.btn-yellow.active{background-color:#fbd972!important;border-color:#f9cf4f}.btn-yellow.no-border.active{background-color:#fad463!important;border-color:#fad463}.btn-yellow.disabled,.btn-yellow.disabled.active,.btn-yellow.disabled:active,.btn-yellow.disabled:focus,.btn-yellow.disabled:hover,.btn-yellow[disabled],.btn-yellow[disabled].active,.btn-yellow[disabled]:active,.btn-yellow[disabled]:focus,.btn-yellow[disabled]:hover,fieldset[disabled] .btn-yellow,fieldset[disabled] .btn-yellow.active,fieldset[disabled] .btn-yellow:active,fieldset[disabled] .btn-yellow:focus,fieldset[disabled] .btn-yellow:hover{background-color:#fee188!important;border-color:#fee188}.btn-light{color:#888!important;text-shadow:0 -1px 0 rgba(250,250,250,.25)!important}.btn-light,.btn-light:focus{background-color:#e7e7e7!important;border-color:#e7e7e7}.btn-light:active,.btn-light:hover,.open .btn-light.dropdown-toggle{background-color:#d9d9d9!important;border-color:#e7e7e7}.btn-light.no-border:active,.btn-light.no-border:hover{border-color:#d9d9d9}.btn-light.no-hover:active,.btn-light.no-hover:hover{background-color:#e7e7e7!important}.btn-light.active{background-color:#e0e0e0!important;border-color:#cecece}.btn-light.no-border.active{background-color:#d8d8d8!important;border-color:#d8d8d8}.btn-light.disabled,.btn-light.disabled.active,.btn-light.disabled:active,.btn-light.disabled:focus,.btn-light.disabled:hover,.btn-light[disabled],.btn-light[disabled].active,.btn-light[disabled]:active,.btn-light[disabled]:focus,.btn-light[disabled]:hover,fieldset[disabled] .btn-light,fieldset[disabled] .btn-light.active,fieldset[disabled] .btn-light:active,fieldset[disabled] .btn-light:focus,fieldset[disabled] .btn-light:hover{background-color:#e7e7e7!important;border-color:#e7e7e7}.btn-light.btn-xs:after{left:-2px;right:-2px;top:-2px;bottom:-2px}.btn-light.btn-sm:after{left:-4px;right:-4px;top:-4px;bottom:-4px}.btn-light .btn-lg:after{left:-6px;right:-6px;top:-6px;bottom:-6px}.btn.btn-white{text-shadow:none!important;background-color:#FFF!important}.btn.btn-white.no-hover:active,.btn.btn-white.no-hover:hover{background-color:#FFF!important}.btn.btn-white.active,.btn.btn-white:focus{box-shadow:inset 1px 1px 2px 0 rgba(0,0,0,.1)!important}.btn.btn-white.active.btn-bold,.btn.btn-white:focus.btn-bold{box-shadow:inset 1px 1px 3px 0 rgba(0,0,0,.15)!important}.btn.btn-white.active:after{display:none}.btn.btn-white{border-color:#ccc;color:#444!important}.btn.btn-white.active,.btn.btn-white:active,.btn.btn-white:focus,.btn.btn-white:hover,.open .btn.btn-white.dropdown-toggle{background-color:#ebebeb!important;border-color:#ccc}.btn.btn-white:hover{color:#3a3434!important}.btn.btn-white.disabled,.btn.btn-white.disabled.active,.btn.btn-white.disabled:active,.btn.btn-white.disabled:focus,.btn.btn-white.disabled:hover,.btn.btn-white.no-border:active,.btn.btn-white.no-border:hover,.btn.btn-white[disabled],.btn.btn-white[disabled].active,.btn.btn-white[disabled]:active,.btn.btn-white[disabled]:focus,.btn.btn-white[disabled]:hover,fieldset[disabled] .btn.btn-white,fieldset[disabled] .btn.btn-white.active,fieldset[disabled] .btn.btn-white:active,fieldset[disabled] .btn.btn-white:focus,fieldset[disabled] .btn.btn-white:hover{border-color:#ccc}.btn-white.btn-default{border-color:#abbac3;color:#80909a!important}.btn-white.btn-default.active,.btn-white.btn-default:active,.btn-white.btn-default:focus,.btn-white.btn-default:hover,.open .btn-white.btn-default.dropdown-toggle{background-color:#eff2f4!important;border-color:#abbac3}.btn-white.btn-default:hover{color:#6b8595!important}.btn-white.btn-default.disabled,.btn-white.btn-default.disabled.active,.btn-white.btn-default.disabled:active,.btn-white.btn-default.disabled:focus,.btn-white.btn-default.disabled:hover,.btn-white.btn-default.no-border:active,.btn-white.btn-default.no-border:hover,.btn-white.btn-default[disabled],.btn-white.btn-default[disabled].active,.btn-white.btn-default[disabled]:active,.btn-white.btn-default[disabled]:focus,.btn-white.btn-default[disabled]:hover,fieldset[disabled] .btn-white.btn-default,fieldset[disabled] .btn-white.btn-default.active,fieldset[disabled] .btn-white.btn-default:active,fieldset[disabled] .btn-white.btn-default:focus,fieldset[disabled] .btn-white.btn-default:hover{border-color:#abbac3}.btn-white.btn-primary{border-color:#8aafce;color:#6688a6!important}.btn-white.btn-primary.active,.btn-white.btn-primary:active,.btn-white.btn-primary:focus,.btn-white.btn-primary:hover,.open .btn-white.btn-primary.dropdown-toggle{background-color:#eaf2f8!important;border-color:#8aafce}.btn-white.btn-primary:hover{color:#537c9f!important}.btn-white.btn-primary.disabled,.btn-white.btn-primary.disabled.active,.btn-white.btn-primary.disabled:active,.btn-white.btn-primary.disabled:focus,.btn-white.btn-primary.disabled:hover,.btn-white.btn-primary.no-border:active,.btn-white.btn-primary.no-border:hover,.btn-white.btn-primary[disabled],.btn-white.btn-primary[disabled].active,.btn-white.btn-primary[disabled]:active,.btn-white.btn-primary[disabled]:focus,.btn-white.btn-primary[disabled]:hover,fieldset[disabled] .btn-white.btn-primary,fieldset[disabled] .btn-white.btn-primary.active,fieldset[disabled] .btn-white.btn-primary:active,fieldset[disabled] .btn-white.btn-primary:focus,fieldset[disabled] .btn-white.btn-primary:hover{border-color:#8aafce}.btn-white.btn-success{border-color:#a7c9a1;color:#81a87b!important}.btn-white.btn-success.active,.btn-white.btn-success:active,.btn-white.btn-success:focus,.btn-white.btn-success:hover,.open .btn-white.btn-success.dropdown-toggle{background-color:#edf4eb!important;border-color:#a7c9a1}.btn-white.btn-success:hover{color:#6ea465!important}.btn-white.btn-success.disabled,.btn-white.btn-success.disabled.active,.btn-white.btn-success.disabled:active,.btn-white.btn-success.disabled:focus,.btn-white.btn-success.disabled:hover,.btn-white.btn-success.no-border:active,.btn-white.btn-success.no-border:hover,.btn-white.btn-success[disabled],.btn-white.btn-success[disabled].active,.btn-white.btn-success[disabled]:active,.btn-white.btn-success[disabled]:focus,.btn-white.btn-success[disabled]:hover,fieldset[disabled] .btn-white.btn-success,fieldset[disabled] .btn-white.btn-success.active,fieldset[disabled] .btn-white.btn-success:active,fieldset[disabled] .btn-white.btn-success:focus,fieldset[disabled] .btn-white.btn-success:hover{border-color:#a7c9a1}.btn-white.btn-danger{border-color:#d7a59d;color:#b7837a!important}.btn-white.btn-danger.active,.btn-white.btn-danger:active,.btn-white.btn-danger:focus,.btn-white.btn-danger:hover,.open .btn-white.btn-danger.dropdown-toggle{background-color:#fbf4f3!important;border-color:#d7a59d}.btn-white.btn-danger:hover{color:#b46f64!important}.btn-white.btn-danger.disabled,.btn-white.btn-danger.disabled.active,.btn-white.btn-danger.disabled:active,.btn-white.btn-danger.disabled:focus,.btn-white.btn-danger.disabled:hover,.btn-white.btn-danger.no-border:active,.btn-white.btn-danger.no-border:hover,.btn-white.btn-danger[disabled],.btn-white.btn-danger[disabled].active,.btn-white.btn-danger[disabled]:active,.btn-white.btn-danger[disabled]:focus,.btn-white.btn-danger[disabled]:hover,fieldset[disabled] .btn-white.btn-danger,fieldset[disabled] .btn-white.btn-danger.active,fieldset[disabled] .btn-white.btn-danger:active,fieldset[disabled] .btn-white.btn-danger:focus,fieldset[disabled] .btn-white.btn-danger:hover{border-color:#d7a59d}.btn-white.btn-warning{border-color:#e7b979;color:#daa458!important}.btn-white.btn-warning.active,.btn-white.btn-warning:active,.btn-white.btn-warning:focus,.btn-white.btn-warning:hover,.open .btn-white.btn-warning.dropdown-toggle{background-color:#fef7ec!important;border-color:#e7b979}.btn-white.btn-warning:hover{color:#db9a3d!important}.btn-white.btn-warning.disabled,.btn-white.btn-warning.disabled.active,.btn-white.btn-warning.disabled:active,.btn-white.btn-warning.disabled:focus,.btn-white.btn-warning.disabled:hover,.btn-white.btn-warning.no-border:active,.btn-white.btn-warning.no-border:hover,.btn-white.btn-warning[disabled],.btn-white.btn-warning[disabled].active,.btn-white.btn-warning[disabled]:active,.btn-white.btn-warning[disabled]:focus,.btn-white.btn-warning[disabled]:hover,fieldset[disabled] .btn-white.btn-warning,fieldset[disabled] .btn-white.btn-warning.active,fieldset[disabled] .btn-white.btn-warning:active,fieldset[disabled] .btn-white.btn-warning:focus,fieldset[disabled] .btn-white.btn-warning:hover{border-color:#e7b979}.btn-white.btn-info{border-color:#8fbcd9;color:#70a0c1!important}.btn-white.btn-info.active,.btn-white.btn-info:active,.btn-white.btn-info:focus,.btn-white.btn-info:hover,.open .btn-white.btn-info.dropdown-toggle{background-color:#eef5fa!important;border-color:#8fbcd9}.btn-white.btn-info:hover{color:#5896bf!important}.btn-white.btn-info.disabled,.btn-white.btn-info.disabled.active,.btn-white.btn-info.disabled:active,.btn-white.btn-info.disabled:focus,.btn-white.btn-info.disabled:hover,.btn-white.btn-info.no-border:active,.btn-white.btn-info.no-border:hover,.btn-white.btn-info[disabled],.btn-white.btn-info[disabled].active,.btn-white.btn-info[disabled]:active,.btn-white.btn-info[disabled]:focus,.btn-white.btn-info[disabled]:hover,fieldset[disabled] .btn-white.btn-info,fieldset[disabled] .btn-white.btn-info.active,fieldset[disabled] .btn-white.btn-info:active,fieldset[disabled] .btn-white.btn-info:focus,fieldset[disabled] .btn-white.btn-info:hover{border-color:#8fbcd9}.btn-white.btn-inverse{border-color:#959595;color:#555!important}.btn-white.btn-inverse.active,.btn-white.btn-inverse:active,.btn-white.btn-inverse:focus,.btn-white.btn-inverse:hover,.open .btn-white.btn-inverse.dropdown-toggle{background-color:#e4e4e4!important;border-color:#959595}.btn-white.btn-inverse:hover{color:#4c4545!important}.btn-white.btn-inverse.disabled,.btn-white.btn-inverse.disabled.active,.btn-white.btn-inverse.disabled:active,.btn-white.btn-inverse.disabled:focus,.btn-white.btn-inverse.disabled:hover,.btn-white.btn-inverse.no-border:active,.btn-white.btn-inverse.no-border:hover,.btn-white.btn-inverse[disabled],.btn-white.btn-inverse[disabled].active,.btn-white.btn-inverse[disabled]:active,.btn-white.btn-inverse[disabled]:focus,.btn-white.btn-inverse[disabled]:hover,fieldset[disabled] .btn-white.btn-inverse,fieldset[disabled] .btn-white.btn-inverse.active,fieldset[disabled] .btn-white.btn-inverse:active,fieldset[disabled] .btn-white.btn-inverse:focus,fieldset[disabled] .btn-white.btn-inverse:hover{border-color:#959595}.btn-white.btn-pink{border-color:#d299ae;color:#af6f87!important}.btn-white.btn-pink.active,.btn-white.btn-pink:active,.btn-white.btn-pink:focus,.btn-white.btn-pink:hover,.open .btn-white.btn-pink.dropdown-toggle{background-color:#fbeff4!important;border-color:#d299ae}.btn-white.btn-pink:hover{color:#ac5978!important}.btn-white.btn-pink.disabled,.btn-white.btn-pink.disabled.active,.btn-white.btn-pink.disabled:active,.btn-white.btn-pink.disabled:focus,.btn-white.btn-pink.disabled:hover,.btn-white.btn-pink.no-border:active,.btn-white.btn-pink.no-border:hover,.btn-white.btn-pink[disabled],.btn-white.btn-pink[disabled].active,.btn-white.btn-pink[disabled]:active,.btn-white.btn-pink[disabled]:focus,.btn-white.btn-pink[disabled]:hover,fieldset[disabled] .btn-white.btn-pink,fieldset[disabled] .btn-white.btn-pink.active,fieldset[disabled] .btn-white.btn-pink:active,fieldset[disabled] .btn-white.btn-pink:focus,fieldset[disabled] .btn-white.btn-pink:hover{border-color:#d299ae}.btn-white.btn-purple{border-color:#b7b1c6;color:#7d6fa2!important}.btn-white.btn-purple.active,.btn-white.btn-purple:active,.btn-white.btn-purple:focus,.btn-white.btn-purple:hover,.open .btn-white.btn-purple.dropdown-toggle{background-color:#efedf5!important;border-color:#b7b1c6}.btn-white.btn-purple:hover{color:#6d5b9c!important}.btn-white.btn-purple.disabled,.btn-white.btn-purple.disabled.active,.btn-white.btn-purple.disabled:active,.btn-white.btn-purple.disabled:focus,.btn-white.btn-purple.disabled:hover,.btn-white.btn-purple.no-border:active,.btn-white.btn-purple.no-border:hover,.btn-white.btn-purple[disabled],.btn-white.btn-purple[disabled].active,.btn-white.btn-purple[disabled]:active,.btn-white.btn-purple[disabled]:focus,.btn-white.btn-purple[disabled]:hover,fieldset[disabled] .btn-white.btn-purple,fieldset[disabled] .btn-white.btn-purple.active,fieldset[disabled] .btn-white.btn-purple:active,fieldset[disabled] .btn-white.btn-purple:focus,fieldset[disabled] .btn-white.btn-purple:hover{border-color:#b7b1c6}.btn-white.btn-yellow{border-color:#ecd181;color:#d3a61a!important}.btn-white.btn-yellow.active,.btn-white.btn-yellow:active,.btn-white.btn-yellow:focus,.btn-white.btn-yellow:hover,.open .btn-white.btn-yellow.dropdown-toggle{background-color:#fdf7e4!important;border-color:#ecd181}.btn-white.btn-yellow:hover{color:#c29712!important}.btn-white.btn-yellow.disabled,.btn-white.btn-yellow.disabled.active,.btn-white.btn-yellow.disabled:active,.btn-white.btn-yellow.disabled:focus,.btn-white.btn-yellow.disabled:hover,.btn-white.btn-yellow.no-border:active,.btn-white.btn-yellow.no-border:hover,.btn-white.btn-yellow[disabled],.btn-white.btn-yellow[disabled].active,.btn-white.btn-yellow[disabled]:active,.btn-white.btn-yellow[disabled]:focus,.btn-white.btn-yellow[disabled]:hover,fieldset[disabled] .btn-white.btn-yellow,fieldset[disabled] .btn-white.btn-yellow.active,fieldset[disabled] .btn-white.btn-yellow:active,fieldset[disabled] .btn-white.btn-yellow:focus,fieldset[disabled] .btn-white.btn-yellow:hover{border-color:#ecd181}.btn-white.btn-grey{border-color:#c6c6c6;color:#8c8c8c!important}.btn-white.btn-grey.active,.btn-white.btn-grey:active,.btn-white.btn-grey:focus,.btn-white.btn-grey:hover,.open .btn-white.btn-grey.dropdown-toggle{background-color:#ededed!important;border-color:#c6c6c6}.btn-white.btn-grey:hover{color:#857979!important}.btn-white.btn-grey.disabled,.btn-white.btn-grey.disabled.active,.btn-white.btn-grey.disabled:active,.btn-white.btn-grey.disabled:focus,.btn-white.btn-grey.disabled:hover,.btn-white.btn-grey.no-border:active,.btn-white.btn-grey.no-border:hover,.btn-white.btn-grey[disabled],.btn-white.btn-grey[disabled].active,.btn-white.btn-grey[disabled]:active,.btn-white.btn-grey[disabled]:focus,.btn-white.btn-grey[disabled]:hover,fieldset[disabled] .btn-white.btn-grey,fieldset[disabled] .btn-white.btn-grey.active,fieldset[disabled] .btn-white.btn-grey:active,fieldset[disabled] .btn-white.btn-grey:focus,fieldset[disabled] .btn-white.btn-grey:hover{border-color:#c6c6c6}.btn.disabled.active,.btn.disabled:active,.btn.disabled:focus,.btn[disabled].active,.btn[disabled]:active,.btn[disabled]:focus{outline:0}.btn.disabled:active,.btn[disabled]:active{top:0;left:0}.btn.active{color:#efe5b5}.btn.active:after{display:inline-block;content:"";position:absolute;border-bottom:1px solid #efe5b5;left:-4px;right:-4px;bottom:-4px}.btn.active.btn-sm:after{left:-3px;right:-3px;bottom:-3px}.btn.active.btn-lg:after{left:-5px;right:-5px;bottom:-5px}.btn.active.btn-minier:after,.btn.active.btn-xs:after{left:-1px;right:-1px;bottom:-2px}.btn.active.btn-minier:after{bottom:-1px}.btn.active.btn-yellow:after{border-bottom-color:#c96338}.btn.active.btn-light{color:#515151}.btn.active.btn-light:after{border-bottom-color:#B5B5B5}.btn>.ace-icon{margin-right:4px}.btn>.ace-icon.icon-on-right{margin-right:0;margin-left:4px}.btn>.icon-only.ace-icon{margin:0!important;text-align:center;padding:0}.btn-large>.ace-icon{margin-right:6px}.btn-large>.ace-icon.icon-on-right{margin-right:0;margin-left:6px}.btn-sm>.ace-icon{margin-right:3px}.btn-sm>.ace-icon.icon-on-right{margin-right:0;margin-left:3px}.btn-minier>.ace-icon,.btn-xs>.ace-icon{margin-right:2px}.btn-minier>.ace-icon.icon-on-right,.btn-xs>.ace-icon.icon-on-right{margin-right:0;margin-left:2px}.btn.btn-link{border:none!important;background:0 0!important;color:#08c!important;text-shadow:none!important;padding:4px 12px!important;line-height:20px!important}.btn.btn-link:hover{background:none!important;text-shadow:none!important}.btn.btn-link.active{background:none!important;text-decoration:underline;color:#009ceb!important}.btn.btn-link.active:after{display:none}.btn.btn-link.disabled,.btn.btn-link[disabled]{background:0 0!important;opacity:.65;filter:alpha(opacity=65);text-decoration:none!important}.btn.btn-no-border{border-width:0!important}.btn-group:first-child{margin-left:0}.btn-group>.btn,.btn-group>.btn+.btn,.btn-group>.btn:first-child{margin:0 1px 0 0}.btn-group>.btn:first-child,.btn-group>.btn:last-child{border-radius:0}.btn-group>.btn>.caret{margin-top:15px;margin-left:1px;border-width:5px;border-top-color:#FFF}.btn-group>.btn.btn-sm>.caret{margin-top:10px;border-width:4px}.btn-group>.btn.btn-large>.caret{margin-top:18px;border-width:6px}.btn-group>.btn.btn-xs>.caret{margin-top:9px;border-width:4px}.btn-group>.btn.btn-minier>.caret{margin-top:7px;border-width:3px}.btn-group>.btn+.btn.dropdown-toggle{padding-right:3px;padding-left:3px}.btn-group>.btn+.btn-large.dropdown-toggle{padding-right:4px;padding-left:4px}.btn-group .dropdown-toggle{border-radius:0}.btn-group+.btn,.btn-group>.btn{margin:0 1px 0 0;border-width:3px}.btn-group+.btn.active:after,.btn-group>.btn.active:after{left:-2px;right:-2px;bottom:-2px;border-bottom-width:1px}.btn-group+.btn-large,.btn-group>.btn-large{border-width:4px}.btn-group+.btn-large.active:after,.btn-group>.btn-large.active:after{left:-3px;right:-3px;bottom:-3px;border-bottom-width:1px}.btn-group+.btn-sm,.btn-group>.btn-sm{border-width:2px}.btn-group+.btn-sm.active:after,.btn-group>.btn-sm.active:after{left:-1px;right:-1px;bottom:-1px;border-bottom-width:1px}.btn-group+.btn-xs,.btn-group>.btn-xs{border-width:1px}.btn-group+.btn-xs.active:after,.btn-group>.btn-xs.active:after{left:0;right:0;bottom:0;border-bottom-width:1px}.btn-group+.btn-minier,.btn-group>.btn-minier{border-width:1px}.btn-group+.btn-minier.active:after,.btn-group>.btn-minier.active:after{left:0;right:0;bottom:0;border-bottom-width:1px}.btn-group>.btn{border-radius:0!important}.btn-group>.btn.btn-round{border-radius:4px!important}.btn-group-vertical>.btn,.btn-group-vertical>.btn+.btn{margin:1px 0 0!important}.btn-group-vertical>.btn:first-child{margin-top:0!important}.btn-group.btn-overlap>.btn{margin-right:-1px}.btn-group.btn-corner>.btn:first-child{border-bottom-left-radius:8px!important;border-top-left-radius:8px!important}.btn-group.btn-corner>.btn:last-child{border-bottom-right-radius:8px!important;border-top-right-radius:8px!important}.btn-group.btn-corner>.btn.btn-sm:first-child{border-bottom-left-radius:6px!important;border-top-left-radius:6px!important}.btn-group.btn-corner>.btn.btn-sm:last-child{border-bottom-right-radius:6px!important;border-top-right-radius:6px!important}.btn-group.btn-corner>.btn.btn-xs:first-child{border-bottom-left-radius:4px!important;border-top-left-radius:4px!important}.btn-group.btn-corner>.btn.btn-xs:last-child{border-bottom-right-radius:4px!important;border-top-right-radius:4px!important}.btn.btn-white{border-width:1px}.btn.btn-bold{border-bottom-width:2px}.btn.btn-round{border-bottom-width:2px;border-radius:4px!important}.btn.btn-app{display:inline-block;width:100px;font-size:18px;font-weight:400;color:#FFF;text-align:center;text-shadow:0 -1px -1px rgba(0,0,0,.2)!important;border:none;border-radius:12px;padding:12px 0 8px;margin:2px;line-height:1.7;position:relative}.btn-app,.btn-app.btn-default,.btn-app.btn-default.disabled:hover,.btn-app.btn-default.no-hover:hover,.btn-app.disabled:hover,.btn-app.no-hover:hover{background:#b4c2cc!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffbcc9d5', endColorstr='#ffabbac3', GradientType=0)!important}.btn-app.btn-default:hover,.btn-app:hover{background:#9baebc!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffa3b5c5', endColorstr='#ff93a6b2', GradientType=0)!important}.btn-app.btn-primary,.btn-app.btn-primary.disabled:hover,.btn-app.btn-primary.no-hover:hover{background:#2a8bcb!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3b98d6', endColorstr='#ff197ec1', GradientType=0)!important}.btn-app.btn-primary:hover{background:#1d6fa6!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff267eb8', endColorstr='#ff136194', GradientType=0)!important}.btn-app.btn-info,.btn-app.btn-info.disabled:hover,.btn-app.btn-info.no-hover:hover{background:#68adde!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff75b5e6', endColorstr='#ff5ba4d5', GradientType=0)!important}.btn-app.btn-info:hover{background:#3f96d4!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff4a9ede', endColorstr='#ff348dc9', GradientType=0)!important}.btn-app.btn-success,.btn-app.btn-success.disabled:hover,.btn-app.btn-success.no-hover:hover{background:#85b558!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff8ebf60', endColorstr='#ff7daa50', GradientType=0)!important}.btn-app.btn-success:hover{background:#6c9842!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff74a844', endColorstr='#ff648740', GradientType=0)!important}.btn-app.btn-danger,.btn-app.btn-danger.disabled:hover,.btn-app.btn-danger.no-hover:hover{background:#d3413b!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd55b52', endColorstr='#ffd12723', GradientType=0)!important}.btn-app.btn-danger:hover{background:#b52c26!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffc43a30', endColorstr='#ffa51f1c', GradientType=0)!important}.btn-app.btn-warning,.btn-app.btn-warning.disabled:hover,.btn-app.btn-warning.no-hover:hover{background:#ffb44b!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffbf66', endColorstr='#ffffa830', GradientType=0)!important}.btn-app.btn-warning:hover{background:#fe9e19!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffaa33', endColorstr='#fffc9200', GradientType=0)!important}.btn-app.btn-purple,.btn-app.btn-purple.disabled:hover,.btn-app.btn-purple.no-hover:hover{background:#9889c1!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffa696ce', endColorstr='#ff8a7cb4', GradientType=0)!important}.btn-app.btn-purple:hover{background:#7b68af!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff8973be', endColorstr='#ff6d5ca1', GradientType=0)!important}.btn-app.btn-pink,.btn-app.btn-pink.disabled:hover,.btn-app.btn-pink.no-hover:hover{background:#d54c7e!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdb5e8c', endColorstr='#ffce3970', GradientType=0)!important}.btn-app.btn-pink:hover{background:#be2f64!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd2346e', endColorstr='#ffaa2a59', GradientType=0)!important}.btn-app.btn-inverse,.btn-app.btn-inverse.disabled:hover,.btn-app.btn-inverse.no-hover:hover{background:#444!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff555555', endColorstr='#ff333333', GradientType=0)!important}.btn-app.btn-inverse:hover{background:#2b2b2b!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3b3b3b', endColorstr='#ff1a1a1a', GradientType=0)!important}.btn-app.btn-grey,.btn-app.btn-grey.disabled:hover,.btn-app.btn-grey.no-hover:hover{background:#797979!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff898989', endColorstr='#ff696969', GradientType=0)!important}.btn-app.btn-grey:hover{background:#6c6c6c!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff7c7c7c', endColorstr='#ff5c5c5c', GradientType=0)!important}.btn.btn-app.btn-light{color:#5a5a5a!important;text-shadow:0 1px 1px #EEE!important}.btn.btn-app.btn-light,.btn.btn-app.btn-light.disabled:hover,.btn.btn-app.btn-light.no-hover:hover{background:#ededed!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff4f4f4', endColorstr='#ffe6e6e6', GradientType=0)!important}.btn.btn-app.btn-light:hover{background:#e0e0e0!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe7e7e7', endColorstr='#ffd9d9d9', GradientType=0)!important}.btn.btn-app.btn-yellow{color:#963!important;text-shadow:0 -1px 0 rgba(255,255,255,.4)!important}.btn.btn-app.btn-yellow,.btn.btn-app.btn-yellow.disabled:hover,.btn.btn-app.btn-yellow.no-hover:hover{background:#fee088!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffe8a5', endColorstr='#fffcd76a', GradientType=0)!important}.btn.btn-app.btn-yellow:hover{background:#fdd96e!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffe18b', endColorstr='#fffbd051', GradientType=0)!important}.btn.btn-app.btn-sm{width:80px;font-size:16px;border-radius:10px;line-height:1.5}.btn.btn-app.btn-xs{width:64px;font-size:15px;border-radius:8px;padding-bottom:7px;padding-top:8px;line-height:1.45}.btn.btn-app>.ace-icon{display:block;font-size:42px;margin:0 0 4px;line-height:36px;min-width:0;padding:0}.btn.btn-app.btn-sm>.ace-icon{display:block;font-size:32px;line-height:30px;margin:0 0 3px}.btn.btn-app.btn-xs>.ace-icon{display:block;font-size:24px;line-height:24px;margin:0}.btn.btn-app.no-radius{border-radius:0}.btn.btn-app.radius-4{border-radius:4px}.btn.btn-app>.badge,.btn.btn-app>.label{position:absolute!important;top:-2px;right:-2px;padding:1px 3px;text-align:center;font-size:12px;color:#FFF}.btn.btn-app>.badge.badge-left,.btn.btn-app>.badge.label-left,.btn.btn-app>.label.badge-left,.btn.btn-app>.label.label-left{right:auto;left:-2px}.btn.btn-app>.label{padding:1px 6px 3px;font-size:13px}.btn.btn-app.no-radius>.badge,.btn.btn-app.radius-4>.badge{border-radius:3px}.btn.btn-app.no-radius>.badge.no-radius,.btn.btn-app.radius-4>.badge.no-radius{border-radius:0}.btn.btn-app.active{color:#fff}.btn.btn-app.active:after{display:none}.btn.btn-app.active.btn-yellow{color:#963;border-color:#fee188}.btn.btn-app.active.btn-light{color:#515151}.btn.btn-app.btn-light,.btn.btn-app.btn-yellow{-webkit-box-shadow:0 0 0 1px rgba(0,0,0,.08) inset!important;box-shadow:0 0 0 1px rgba(0,0,0,.08) inset!important}.label{border-radius:0;text-shadow:none;font-weight:400;display:inline-block;background-color:#abbac3!important}.label[class*=col-][class*=arrow]{min-height:0}@media screen and (-webkit-min-device-pixel-ratio:0){.badge:empty,.label:empty,::safari-only{display:inline-block}}.badge{text-shadow:none;font-size:12px;padding-top:1px;padding-bottom:3px;font-weight:400;line-height:15px;background-color:#abbac3!important}.badge.no-radius{border-radius:0}.badge.radius-1{border-radius:1px}.badge.radius-2{border-radius:2px}.badge.radius-3{border-radius:3px}.badge.radius-4{border-radius:4px}.badge.radius-5{border-radius:5px}.badge.radius-6{border-radius:6px}.badge-transparent,.label-transparent{background-color:transparent!important}.badge-grey,.label-grey{background-color:#a0a0a0!important}.badge-info,.label-info{background-color:#3a87ad!important}.badge-primary,.label-primary{background-color:#428bca!important}.badge-success,.label-success{background-color:#82af6f!important}.badge-danger,.badge-important,.label-danger,.label-important{background-color:#d15b47!important}.badge-inverse,.label-inverse{background-color:#333!important}.badge-warning,.label-warning{background-color:#f89406!important}.badge-pink,.label-pink{background-color:#d6487e!important}.badge-purple,.label-purple{background-color:#9585bf!important}.badge-yellow,.label-yellow{background-color:#fee188!important}.badge-light,.label-light{background-color:#e7e7e7!important}.badge-yellow,.label-yellow{color:#963!important;border-color:#fee188}.badge-light,.label-light{color:#888!important}.label.arrowed,.label.arrowed-in{position:relative;z-index:1}.label.arrowed-in:before,.label.arrowed:before{display:inline-block;content:"";position:absolute;top:0;z-index:-1;border:1px solid transparent;border-right-color:#abbac3;-moz-border-right-colors:#abbac3}.label.arrowed-in:before{border-color:#abbac3;border-left-color:transparent!important;-moz-border-left-colors:none!important}.label.arrowed-in-right,.label.arrowed-right{position:relative;z-index:1}.label.arrowed-in-right:after,.label.arrowed-right:after{display:inline-block;content:"";position:absolute;top:0;z-index:-1;border:1px solid transparent;border-left-color:#abbac3;-moz-border-left-colors:#abbac3}.label.arrowed-in-right:after{border-color:#abbac3;border-right-color:transparent!important;-moz-border-right-colors:none!important}.label-info.arrowed:before{border-right-color:#3a87ad;-moz-border-right-colors:#3a87ad}.label-info.arrowed-in:before{border-color:#3a87ad;-moz-border-right-colors:#3a87ad}.label-info.arrowed-right:after{border-left-color:#3a87ad;-moz-border-left-colors:#3a87ad}.label-info.arrowed-in-right:after{border-color:#3a87ad;-moz-border-left-colors:#3a87ad}.label-primary.arrowed:before{border-right-color:#428bca;-moz-border-right-colors:#428bca}.label-primary.arrowed-in:before{border-color:#428bca;-moz-border-right-colors:#428bca}.label-primary.arrowed-right:after{border-left-color:#428bca;-moz-border-left-colors:#428bca}.label-primary.arrowed-in-right:after{border-color:#428bca;-moz-border-left-colors:#428bca}.label-success.arrowed:before{border-right-color:#82af6f;-moz-border-right-colors:#82af6f}.label-success.arrowed-in:before{border-color:#82af6f;-moz-border-right-colors:#82af6f}.label-success.arrowed-right:after{border-left-color:#82af6f;-moz-border-left-colors:#82af6f}.label-success.arrowed-in-right:after{border-color:#82af6f;-moz-border-left-colors:#82af6f}.label-warning.arrowed:before{border-right-color:#f89406;-moz-border-right-colors:#f89406}.label-warning.arrowed-in:before{border-color:#f89406;-moz-border-right-colors:#f89406}.label-warning.arrowed-right:after{border-left-color:#f89406;-moz-border-left-colors:#f89406}.label-warning.arrowed-in-right:after{border-color:#f89406;-moz-border-left-colors:#f89406}.label-important.arrowed:before{border-right-color:#d15b47;-moz-border-right-colors:#d15b47}.label-important.arrowed-in:before{border-color:#d15b47;-moz-border-right-colors:#d15b47}.label-important.arrowed-right:after{border-left-color:#d15b47;-moz-border-left-colors:#d15b47}.label-important.arrowed-in-right:after{border-color:#d15b47;-moz-border-left-colors:#d15b47}.label-danger.arrowed:before{border-right-color:#d15b47;-moz-border-right-colors:#d15b47}.label-danger.arrowed-in:before{border-color:#d15b47;-moz-border-right-colors:#d15b47}.label-danger.arrowed-right:after{border-left-color:#d15b47;-moz-border-left-colors:#d15b47}.label-danger.arrowed-in-right:after{border-color:#d15b47;-moz-border-left-colors:#d15b47}.label-inverse.arrowed:before{border-right-color:#333;-moz-border-right-colors:#333}.label-inverse.arrowed-in:before{border-color:#333;-moz-border-right-colors:#333}.label-inverse.arrowed-right:after{border-left-color:#333;-moz-border-left-colors:#333}.label-inverse.arrowed-in-right:after{border-color:#333;-moz-border-left-colors:#333}.label-pink.arrowed:before{border-right-color:#d6487e;-moz-border-right-colors:#d6487e}.label-pink.arrowed-in:before{border-color:#d6487e;-moz-border-right-colors:#d6487e}.label-pink.arrowed-right:after{border-left-color:#d6487e;-moz-border-left-colors:#d6487e}.label-pink.arrowed-in-right:after{border-color:#d6487e;-moz-border-left-colors:#d6487e}.label-purple.arrowed:before{border-right-color:#9585bf;-moz-border-right-colors:#9585bf}.label-purple.arrowed-in:before{border-color:#9585bf;-moz-border-right-colors:#9585bf}.label-purple.arrowed-right:after{border-left-color:#9585bf;-moz-border-left-colors:#9585bf}.label-purple.arrowed-in-right:after{border-color:#9585bf;-moz-border-left-colors:#9585bf}.label-yellow.arrowed:before{border-right-color:#fee188;-moz-border-right-colors:#fee188}.label-yellow.arrowed-in:before{border-color:#fee188;-moz-border-right-colors:#fee188}.label-yellow.arrowed-right:after{border-left-color:#fee188;-moz-border-left-colors:#fee188}.label-yellow.arrowed-in-right:after{border-color:#fee188;-moz-border-left-colors:#fee188}.label-light.arrowed:before{border-right-color:#e7e7e7;-moz-border-right-colors:#e7e7e7}.label-light.arrowed-in:before{border-color:#e7e7e7;-moz-border-right-colors:#e7e7e7}.label-light.arrowed-right:after{border-left-color:#e7e7e7;-moz-border-left-colors:#e7e7e7}.label-light.arrowed-in-right:after{border-color:#e7e7e7;-moz-border-left-colors:#e7e7e7}.label-grey.arrowed:before{border-right-color:#a0a0a0;-moz-border-right-colors:#a0a0a0}.label-grey.arrowed-in:before{border-color:#a0a0a0;-moz-border-right-colors:#a0a0a0}.label-grey.arrowed-right:after{border-left-color:#a0a0a0;-moz-border-left-colors:#a0a0a0}.label-grey.arrowed-in-right:after{border-color:#a0a0a0;-moz-border-left-colors:#a0a0a0}.label{font-size:12px;line-height:1.15;height:20px}.label.arrowed{margin-left:5px}.label.arrowed:before{left:-10px;border-width:10px 5px}.label.arrowed-in{margin-left:5px}.label.arrowed-in:before{left:-5px;border-width:10px 5px}.label.arrowed-right{margin-right:5px}.label.arrowed-right:after{right:-10px;border-width:10px 5px}.label.arrowed-in-right{margin-right:5px}.label.arrowed-in-right:after{right:-5px;border-width:10px 5px}.label-lg{padding:.3em .6em .4em;font-size:13px;line-height:1.1;height:24px}.label-lg.arrowed{margin-left:6px}.label-lg.arrowed:before{left:-12px;border-width:12px 6px}.label-lg.arrowed-in{margin-left:6px}.label-lg.arrowed-in:before{left:-6px;border-width:12px 6px}.label-lg.arrowed-right{margin-right:6px}.label-lg.arrowed-right:after{right:-12px;border-width:12px 6px}.label-lg.arrowed-in-right{margin-right:6px}.label-lg.arrowed-in-right:after{right:-6px;border-width:12px 6px}.label-xlg{padding:.3em .7em .4em;font-size:14px;line-height:1.3;height:28px}.label-xlg.arrowed{margin-left:7px}.label-xlg.arrowed:before{left:-14px;border-width:14px 7px}.label-xlg.arrowed-in{margin-left:7px}.label-xlg.arrowed-in:before{left:-7px;border-width:14px 7px}.label-xlg.arrowed-right{margin-right:7px}.label-xlg.arrowed-right:after{right:-14px;border-width:14px 7px}.label-xlg.arrowed-in-right{margin-right:7px}.label-xlg.arrowed-in-right:after{right:-7px;border-width:14px 7px}.label-sm{padding:.2em .4em .3em;font-size:11px;line-height:1;height:18px}.label-sm.arrowed{margin-left:4px}.label-sm.arrowed:before{left:-8px;border-width:9px 4px}.label-sm.arrowed-in{margin-left:4px}.label-sm.arrowed-in:before{left:-4px;border-width:9px 4px}.label-sm.arrowed-right{margin-right:4px}.label-sm.arrowed-right:after{right:-8px;border-width:9px 4px}.label-sm.arrowed-in-right{margin-right:4px}.label-sm.arrowed-in-right:after{right:-4px;border-width:9px 4px}.label>.ace-icon,.label>span{line-height:1;vertical-align:bottom}@media screen and (-webkit-min-device-pixel-ratio:1.08) and (-webkit-max-device-pixel-ratio:1.15),screen and (-webkit-min-device-pixel-ratio:1.3) and (-webkit-max-device-pixel-ratio:1.35),screen and (-webkit-min-device-pixel-ratio:1.7) and (-webkit-max-device-pixel-ratio:1.75){.label:not(.label-lg):not(.label-xlg):not(.label-sm).arrowed:before{border-width:10px 6px 11px;left:-11px}.label:not(.label-lg):not(.label-xlg):not(.label-sm).arrowed-right:after{border-width:10px 6px 11px;right:-11px}.label:not(.label-lg):not(.label-xlg):not(.label-sm).arrowed-in:before{border-width:10px 5px 10.5px;left:-6px}.label:not(.label-lg):not(.label-xlg):not(.label-sm).arrowed-in-right:after{border-width:10px 5px 10.5px;right:-6px}}@media screen and (min--moz-device-pixel-ratio:1.08) and (max--moz-device-pixel-ratio:1.15),screen and (min--moz-device-pixel-ratio:1.3) and (max--moz-device-pixel-ratio:1.35),screen and (min--moz-device-pixel-ratio:1.7) and (max--moz-device-pixel-ratio:1.75){.label:not(.label-lg):not(.label-xlg):not(.label-sm).arrowed:before{border-width:10px 6px 11px;left:-11px}.label:not(.label-lg):not(.label-xlg):not(.label-sm).arrowed-right:after{border-width:10px 6px 11px;right:-11px}.label:not(.label-lg):not(.label-xlg):not(.label-sm).arrowed-in:before{border-width:10px 5px 10.5px;left:-6px}.label:not(.label-lg):not(.label-xlg):not(.label-sm).arrowed-in-right:after{border-width:10px 5px 10.5px;right:-6px}}@media screen and (-webkit-min-device-pixel-ratio:1.3) and (-webkit-max-device-pixel-ratio:1.34){.label:not(.label-lg):not(.label-xlg):not(.label-sm).arrowed:before{border-width:10px 6px 11px;left:-11.5px}.label:not(.label-lg):not(.label-xlg):not(.label-sm).arrowed-right:after{border-width:10px 6px 11px;right:-11.5px}}@media screen and (min--moz-device-pixel-ratio:1.3) and (max--moz-device-pixel-ratio:1.34){.label:not(.label-lg):not(.label-xlg):not(.label-sm).arrowed:before{border-width:10px 6px 11px;left:-11.5px}.label:not(.label-lg):not(.label-xlg):not(.label-sm).arrowed-right:after{border-width:10px 6px 11px;right:-11.5px}}@media only screen and (-webkit-max-device-pixel-ratio:1.7) and (-webkit-min-device-pixel-ratio:1.75){.label:not(.label-lg):not(.label-xlg):not(.label-sm).arrowed-in:before{border-width:10px 5px;left:-6px}.label:not(.label-lg):not(.label-xlg):not(.label-sm).arrowed-in-right:after{border-width:10px 5px;right:-6px}}@media only screen and (min--moz-device-pixel-ratio:1.7) and (max--moz-device-pixel-ratio:1.75){.label:not(.label-lg):not(.label-xlg):not(.label-sm).arrowed-in:before{border-width:10px 5px;left:-6px}.label:not(.label-lg):not(.label-xlg):not(.label-sm).arrowed-in-right:after{border-width:10px 5px;right:-6px}}.dropdown-menu>.active>a>.ace-icon,.dropdown-menu>li>a:focus>.ace-icon,.dropdown-menu>li>a:hover>.ace-icon,.dropdown-submenu:focus>a>.ace-icon,.dropdown-submenu:hover>a>.ace-icon,.icon-white,.nav-list>.active>a>.ace-icon,.nav-pills>.active>a>.ace-icon,.navbar-inverse .nav>.active>a>.ace-icon{background-image:none}.dropdown-menu{border-radius:0!important;-webkit-box-shadow:0 2px 4px rgba(0,0,0,.2);box-shadow:0 2px 4px rgba(0,0,0,.2)}.dropdown-menu>li>a{font-size:13px;padding-left:11px;padding-right:11px;margin-bottom:1px;margin-top:1px}.dropdown-menu.dropdown-only-icon{min-width:50px}.dropdown-menu.dropdown-only-icon>li{margin:0 4px}.dropdown-menu.dropdown-only-icon>li>a .ace-icon{width:18px;display:inline-block;text-align:center}.dropdown-menu.dropdown-only-icon>li>a .icon-2x{width:36px}.dropdown-menu .dropdown-submenu:hover>a,.dropdown-menu>li.active>a,.dropdown-menu>li.active>a:hover,.dropdown-menu>li>a:active,.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background:#4f99c6;color:#fff}.dropdown-default .dropdown-submenu:hover>a,.dropdown-default>li.active>a,.dropdown-default>li.active>a:hover,.dropdown-default>li>a:active,.dropdown-default>li>a:focus,.dropdown-default>li>a:hover{background:#abbac3;color:#fff}.dropdown-info .dropdown-submenu:hover>a,.dropdown-info>li.active>a,.dropdown-info>li.active>a:hover,.dropdown-info>li>a:active,.dropdown-info>li>a:focus,.dropdown-info>li>a:hover{background:#6fb3e0;color:#fff}.dropdown-primary .dropdown-submenu:hover>a,.dropdown-primary>li.active>a,.dropdown-primary>li.active>a:hover,.dropdown-primary>li>a:active,.dropdown-primary>li>a:focus,.dropdown-primary>li>a:hover{background:#428bca;color:#fff}.dropdown-success .dropdown-submenu:hover>a,.dropdown-success>li.active>a,.dropdown-success>li.active>a:hover,.dropdown-success>li>a:active,.dropdown-success>li>a:focus,.dropdown-success>li>a:hover{background:#87b87f;color:#fff}.dropdown-warning .dropdown-submenu:hover>a,.dropdown-warning>li.active>a,.dropdown-warning>li.active>a:hover,.dropdown-warning>li>a:active,.dropdown-warning>li>a:focus,.dropdown-warning>li>a:hover{background:#ffa24d;color:#fff}.dropdown-danger .dropdown-submenu:hover>a,.dropdown-danger>li.active>a,.dropdown-danger>li.active>a:hover,.dropdown-danger>li>a:active,.dropdown-danger>li>a:focus,.dropdown-danger>li>a:hover{background:#d15b47;color:#fff}.dropdown-inverse .dropdown-submenu:hover>a,.dropdown-inverse>li.active>a,.dropdown-inverse>li.active>a:hover,.dropdown-inverse>li>a:active,.dropdown-inverse>li>a:focus,.dropdown-inverse>li>a:hover{background:#555;color:#fff}.dropdown-purple .dropdown-submenu:hover>a,.dropdown-purple>li.active>a,.dropdown-purple>li.active>a:hover,.dropdown-purple>li>a:active,.dropdown-purple>li>a:focus,.dropdown-purple>li>a:hover{background:#9585bf;color:#fff}.dropdown-pink .dropdown-submenu:hover>a,.dropdown-pink>li.active>a,.dropdown-pink>li.active>a:hover,.dropdown-pink>li>a:active,.dropdown-pink>li>a:focus,.dropdown-pink>li>a:hover{background:#d6487e;color:#fff}.dropdown-grey .dropdown-submenu:hover>a,.dropdown-grey>li.active>a,.dropdown-grey>li.active>a:hover,.dropdown-grey>li>a:active,.dropdown-grey>li>a:focus,.dropdown-grey>li>a:hover{background:#a0a0a0;color:#fff}.dropdown-light .dropdown-submenu:hover>a,.dropdown-light>li.active>a,.dropdown-light>li.active>a:hover,.dropdown-light>li>a:active,.dropdown-light>li>a:focus,.dropdown-light>li>a:hover{background:#e7e7e7;color:#333}.dropdown-lighter .dropdown-submenu:hover>a,.dropdown-lighter>li.active>a,.dropdown-lighter>li.active>a:hover,.dropdown-lighter>li>a:active,.dropdown-lighter>li>a:focus,.dropdown-lighter>li>a:hover{background:#efefef;color:#444}.dropdown-lightest .dropdown-submenu:hover>a,.dropdown-lightest>li.active>a,.dropdown-lightest>li.active>a:hover,.dropdown-lightest>li>a:active,.dropdown-lightest>li>a:focus,.dropdown-lightest>li>a:hover{background:#f3f3f3;color:#444}.dropdown-yellow .dropdown-submenu:hover>a,.dropdown-yellow>li.active>a,.dropdown-yellow>li.active>a:hover,.dropdown-yellow>li>a:active,.dropdown-yellow>li>a:focus,.dropdown-yellow>li>a:hover{background:#fee188;color:#444}.dropdown-yellow2 .dropdown-submenu:hover>a,.dropdown-yellow2>li.active>a,.dropdown-yellow2>li.active>a:hover,.dropdown-yellow2>li>a:active,.dropdown-yellow2>li>a:focus,.dropdown-yellow2>li>a:hover{background:#f9e8b3;color:#444}.dropdown-light-blue .dropdown-submenu:hover>a,.dropdown-light-blue>li.active>a,.dropdown-light-blue>li.active>a:hover,.dropdown-light-blue>li>a:active,.dropdown-light-blue>li>a:focus,.dropdown-light-blue>li>a:hover{background:#ecf3f9;color:#456}.dropdown-light .dropdown-submenu:hover>a:after,.dropdown-lighter .dropdown-submenu:hover>a:after,.dropdown-lightest .dropdown-submenu:hover>a:after{border-left-color:#444}.dropdown-menu.dropdown-close{top:92%;left:-5px}.dropdown-menu.dropdown-close.dropdown-menu-right{left:auto;right:-5px}.dropdown-menu.dropdown-closer{top:80%;left:-10px}.dropdown-menu.dropdown-closer.dropdown-menu-right{right:-10px;left:auto}.dropup>.dropdown-menu,.navbar-fixed-bottom .dropdown>.dropdown-menu{top:auto!important;bottom:100%}.dropup>.dropdown-menu.dropdown-close,.navbar-fixed-bottom .dropdown>.dropdown-menu.dropdown-close{bottom:92%}.dropup>.dropdown-menu.dropdown-closer,.navbar-fixed-bottom .dropdown>.dropdown-menu.dropdown-closer{bottom:80%}.dropdown-submenu>.dropdown-menu{border-radius:0}.dropdown-submenu>a:after{margin-right:-5px}.dropdown-50{min-width:50px}.dropdown-75{min-width:75px}.dropdown-100{min-width:100px}.dropdown-125{min-width:125px}.dropdown-150{min-width:150px}.dropdown-hover{position:relative}.dropdown-hover:before{display:block;content:"";position:absolute;top:-2px;bottom:-2px;left:-2px;right:-2px;background-color:transparent}.dropdown-hover:hover>.dropdown-menu{display:block}.dropdown-menu>.dropdown-hover>.dropdown-menu{top:-5px;left:99%;right:auto}.dropdown-menu>.dropdown-hover>.dropdown-menu.dropdown-menu-right{left:auto;right:99%}.dropdown-menu>.dropdown-hover.dropup>.dropdown-menu,.dropup .dropdown-menu>.dropdown-hover>.dropdown-menu{top:auto;bottom:-5px}.dropdown-menu.dropdown-caret:before{border-bottom:7px solid rgba(0,0,0,.2);-moz-border-bottom-colors:rgba(0,0,0,.2);border-left:7px solid transparent;border-right:7px solid transparent;content:"";display:inline-block;left:9px;position:absolute;top:-7px}.dropdown-menu.dropdown-caret:after{border-bottom:6px solid #FFF;-moz-border-bottom-colors:#FFF;border-left:6px solid transparent;border-right:6px solid transparent;content:"";display:inline-block;left:10px;position:absolute;top:-6px}.dropdown-menu.dropdown-menu-right.dropdown-caret:before{left:auto;right:9px}.dropdown-menu.dropdown-menu-right.dropdown-caret:after{left:auto;right:10px}.dropup>.dropdown-menu.dropdown-caret:before,.navbar-fixed-bottom .dropdown>.dropdown-menu.dropdown-caret:before{border-bottom-width:0;border-top:7px solid rgba(0,0,0,.2);-moz-border-top-colors:rgba(0,0,0,.2);bottom:-7px;top:auto}.dropup>.dropdown-menu.dropdown-caret:after,.navbar-fixed-bottom .dropdown>.dropdown-menu.dropdown-caret:after{border-bottom-width:0;border-top:6px solid #FFF;-moz-border-top-colors:#FFF;bottom:-6px;top:auto}.dropdown-colorpicker>.dropdown-menu{padding:4px;min-width:130px;max-width:130px;top:80%;left:-7px}.dropdown-colorpicker>.dropdown-menu.dropdown-menu-right{right:-7px;left:auto}.dropdown-colorpicker>.dropdown-menu>li{display:block;float:left;width:20px;height:20px;margin:2px}.dropdown-colorpicker>.dropdown-menu>li>.colorpick-btn{display:block;width:20px;height:20px;margin:0;padding:0;border-radius:0;position:relative;-webkit-transition:all ease .1s;-o-transition:all ease .1s;transition:all ease .1s}.dropdown-colorpicker>.dropdown-menu>li>.colorpick-btn:hover{text-decoration:none;opacity:.8;filter:alpha(opacity=80);-webkit-transform:scale(1.08,1.08);-ms-transform:scale(1.08,1.08);-o-transform:scale(1.08,1.08);transform:scale(1.08,1.08)}.dropdown-colorpicker>.dropdown-menu>li>.colorpick-btn.selected:after{content:"\f00c";display:inline-block;font-family:FontAwesome;font-size:11px;color:#FFF;position:absolute;left:0;right:0;text-align:center;line-height:20px}.btn-colorpicker{display:inline-block;width:20px;height:20px;background-color:#DDD;vertical-align:middle;border-radius:0}.dropdown-navbar{padding:0;width:240px;-webkit-box-shadow:0 2px 4px rgba(30,30,100,.25);box-shadow:0 2px 4px rgba(30,30,100,.25);border-color:#bcd4e5}.dropdown-navbar>li{padding:0 8px;background-color:#FFF}.dropdown-navbar>li.dropdown-header{text-shadow:none;padding-top:0;padding-bottom:0;line-height:34px;font-size:13px;font-weight:700;text-transform:none;border-bottom:1px solid}.dropdown-navbar>li>.ace-icon,.dropdown-navbar>li>a>.ace-icon{margin-right:5px!important;color:#555;font-size:14px}.dropdown-navbar>li>a{padding:10px 2px;margin:0;border-top:1px solid;font-size:12px;line-height:16px;color:#555}.dropdown-navbar>li>a:active,.dropdown-navbar>li>a:focus,.dropdown-navbar>li>a:hover{background-color:transparent!important;color:#555}.dropdown-navbar>li>a .progress{margin-bottom:0;margin-top:4px}.dropdown-navbar>li>a .badge{line-height:16px;padding-right:4px;padding-left:4px;font-size:12px}.dropdown-navbar>li.dropdown-header+li>a,.dropdown-navbar>li:first-child>a{border-top-width:0}.dropdown-navbar>li.dropdown-footer>a{color:#4F99C6;text-align:center;font-size:13px}.dropdown-navbar>li.dropdown-footer>a:hover{background-color:#FFF;color:#4F99C6;text-decoration:underline}.dropdown-navbar>li.dropdown-footer>a:hover>.ace-icon{text-decoration:none}.dropdown-navbar>li:hover{background-color:#f4f9fc!important}.dropdown-navbar>li.dropdown-header{background-color:#ecf2f7!important;color:#8090a0;border-bottom-color:#bcd4e5}.dropdown-navbar>li.dropdown-header>.ace-icon{color:#8090a0}.dropdown-navbar>li>a{border-top-color:#e4ecf3}.dropdown-navbar.navbar-pink{border-color:#e5bcd4}.dropdown-navbar.navbar-pink>li:hover{background-color:#fcf4f9!important}.dropdown-navbar.navbar-pink>li.dropdown-header{background-color:#f7ecf2!important;color:#b471a0;border-bottom-color:#e5bcd4}.dropdown-navbar.navbar-pink>li.dropdown-header>.ace-icon{color:#c06090}.dropdown-navbar.navbar-pink>li>a{border-top-color:#f3e4ec}.dropdown-navbar.navbar-grey{border-color:#e5e5e5}.dropdown-navbar.navbar-grey>li:hover{background-color:#f8f8f8!important}.dropdown-navbar.navbar-grey>li.dropdown-header{background-color:#f2f2f2!important;color:#3a87ad;border-bottom-color:#e5e5e5}.dropdown-navbar.navbar-grey>li.dropdown-header>.ace-icon{color:#3a87ad}.dropdown-navbar.navbar-grey>li>a{border-top-color:#eee}.dropdown-navbar.navbar-green{border-color:#b4d5ac}.dropdown-navbar.navbar-green>li:hover{background-color:#f4f9ef!important}.dropdown-navbar.navbar-green>li.dropdown-header{background-color:#ebf7e4!important;color:#8a6;border-bottom-color:#b4d5ac}.dropdown-navbar.navbar-green>li.dropdown-header>.ace-icon{color:#90c060}.dropdown-navbar.navbar-green>li>a{border-top-color:#ecf3e4}.dropdown-navbar [class*=btn].ace-icon{display:inline-block;margin:0 5px 0 0;width:24px;text-align:center;padding-left:0;padding-right:0}.dropdown-navbar .msg-photo{margin-right:6px;max-width:42px}.dropdown-navbar .msg-body{display:inline-block;line-height:20px;white-space:normal;vertical-align:middle;max-width:175px}.dropdown-navbar .msg-title{display:inline-block;line-height:14px}.dropdown-navbar .msg-time{display:block;font-size:11px;color:#777}.dropdown-navbar .msg-time>.ace-icon{font-size:14px;color:#555}.dropdown-navbar>.dropdown-content{padding:0}.dropdown-navbar>.dropdown-content .dropdown-navbar{list-style:none;margin:0;padding:0!important;-webkit-box-shadow:none;box-shadow:none;width:auto;display:block;float:none;border-width:0;position:static;z-index:auto}.dropdown-navbar .nav-tabs{border-width:0;box-shadow:none;background-color:#F9F9F9!important;top:auto;width:100%}.dropdown-navbar .nav-tabs>li{display:table-cell;width:1%;float:none!important}.dropdown-navbar .nav-tabs>li>a{margin:0 0 0 1px!important;text-align:center;box-shadow:none!important;background-color:#F9F9F9!important;border-width:0!important;border-bottom:2px solid #BECAD1!important}.dropdown-navbar .nav-tabs>li>a:before{display:block;content:"";position:absolute;left:-1px;top:3px;bottom:3px;width:1px;background-color:#BECAD1}.dropdown-navbar .nav-tabs>li:first-child>a{margin-left:0!important}.dropdown-navbar .nav-tabs>li:first-child>a:before{display:none}.dropdown-navbar .nav-tabs>li.active>a{border-bottom:2px solid #79B0CE!important;color:#5085AF!important;background-color:#ECF2F7!important}.dropdown-navbar .tab-content{padding:0!important;border-color:#FFF!important}.dropdown-navbar .tab-content .dropdown-menu{display:block;position:static;margin:0!important;padding-top:2px;border-color:#FFF!important;box-shadow:none!important;width:100%}.dropdown-navbar.navbar-pink .nav-tabs>li.active>a{border-bottom:2px solid #E5BCD4!important;color:#C06090!important;background-color:#F7ECF2!important}.dropdown-navbar.navbar-pink .nav-tabs>li:not(.active)>a:hover{color:#BA7396}.dropdown-navbar.navbar-pink .nav-tabs>li>a:before{background-color:#CEBBCB}.dropdown-navbar.navbar-pink .nav-tabs>li>a{border-bottom-color:#CEBBCD!important}.form-line{margin-bottom:24px;padding-bottom:12px;border-bottom:1px solid #EEE}.form-actions{display:block;background-color:#F5F5F5;border-top:1px solid #E5E5E5;margin-bottom:20px;margin-top:20px;padding:19px 20px 20px}.help-button{display:inline-block;height:22px;width:22px;line-height:22px;text-align:center;padding:0;background-color:#65bcda;color:#FFF;font-size:12px;font-weight:700;cursor:default;margin-left:4px;border-radius:100%;border:2px solid #FFF;-webkit-box-shadow:0 1px 0 1px rgba(0,0,0,.2);box-shadow:0 1px 0 1px rgba(0,0,0,.2)}.help-button:hover{background-color:#65bcda;text-shadow:none}label{font-weight:400;font-size:14px}.form-group>label[class*=col-]{padding-top:4px;margin-bottom:4px}td>label,th>label{margin-bottom:0;line-height:inherit;vertical-align:middle}label.inline{margin-bottom:3px}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],textarea{border-radius:0!important;color:#858585;background-color:#fff;border:1px solid #d5d5d5;padding:5px 4px 6px;font-size:14px;font-family:inherit;-webkit-box-shadow:none!important;box-shadow:none!important;-webkit-transition-duration:.1s;transition-duration:.1s}input[type=color]:hover,input[type=date]:hover,input[type=datetime-local]:hover,input[type=datetime]:hover,input[type=email]:hover,input[type=month]:hover,input[type=number]:hover,input[type=password]:hover,input[type=search]:hover,input[type=tel]:hover,input[type=text]:hover,input[type=time]:hover,input[type=url]:hover,input[type=week]:hover,textarea:hover{border-color:#b5b5b5}input[type=color]:focus,input[type=date]:focus,input[type=datetime-local]:focus,input[type=datetime]:focus,input[type=email]:focus,input[type=month]:focus,input[type=number]:focus,input[type=password]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=time]:focus,input[type=url]:focus,input[type=week]:focus,textarea:focus{-webkit-box-shadow:none;box-shadow:none;color:#696969;border-color:#f59942;background-color:#fff;outline:0}.form-control,select{border-radius:0;-webkit-box-shadow:none!important;box-shadow:none!important;color:#858585;background-color:#fff;border:1px solid #d5d5d5}.form-control:focus,select:focus{color:#696969;border-color:#f59942;background-color:#fff;outline:0}textarea.form-control{padding:5px 9px}select{padding:3px 4px;height:30px}select.form-control{padding:4px 6px}select.form-control[multiple],select[multiple]{height:auto}select.input-sm{border-radius:0;padding:2px 3px}select.input-lg{border-radius:0;padding:6px 8px}input.block{display:block;margin-bottom:9px}textarea.autosize-transition{-webkit-transition-duration:"height 0.2s";transition-duration:"height 0.2s"}.limiterBox{border:1px solid #222;border-top:none;background-color:#333;padding:3px 6px;font-size:13px;color:#FFF;margin-top:6px}.limiterBox:after{display:none}.limiterBox:before{display:block;content:"";position:absolute;width:0;height:0;top:-8px;left:50%;margin-left:-5px;border-color:transparent transparent #333;border-style:solid;-moz-border-bottom-colors:#333;border-width:0 8px 8px}select option,select.form-control option{padding:3px 4px}select option:active,select option:focus,select option:hover,select.form-control option:active,select.form-control option:focus,select.form-control option:hover{background-color:#e5e9ee;color:#111}select option[value=""],select.form-control option[value=""]{padding:0}input[disabled]{color:#848484!important;background-color:#eee!important}input[disabled]:hover{border-color:#d5d5d5!important}input[readonly]{color:#939192;background:#f5f5f5!important;cursor:default}input[readonly]:hover{border-color:#c3c3c3}input[readonly]:focus{-webkit-box-shadow:none;box-shadow:none;border-color:#aaa;background-color:#f9f9f9}.help-inline{font-size:13px!important}.input-icon{position:relative}span.input-icon{display:inline-block}.input-icon>input{padding-left:24px;padding-right:6px}.input-icon.input-icon-right>input{padding-left:6px;padding-right:24px}.input-icon>.ace-icon{padding:0 3px;z-index:2;position:absolute;top:1px;bottom:1px;left:3px;line-height:28px;display:inline-block;color:#909090;font-size:16px}.input-icon.input-icon-right>.ace-icon{left:auto;right:3px}.input-icon>input:focus+.ace-icon{color:#579}.input-icon~.help-inline{padding-left:8px}.form-inline .checkbox [type=checkbox]+label,.form-inline .radio [type=radio]+label,.form-search .checkbox [type=checkbox]+label,.form-search .radio [type=radio]+label{float:left;margin-left:-20px}.form-inline .form-inline .checkbox [type=checkbox]+label,.form-inline .form-inline .radio [type=radio]+label,.form-inline .form-search .checkbox [type=checkbox]+label,.form-inline .form-search .radio [type=radio]+label,.form-search .form-inline .checkbox [type=checkbox]+label,.form-search .form-inline .radio [type=radio]+label,.form-search .form-search .checkbox [type=checkbox]+label,.form-search .form-search .radio [type=radio]+label{margin-left:0;margin-right:3px}.form-search .input-append .search-query:focus,.form-search .input-prepend .search-query:focus{-webkit-box-shadow:none;box-shadow:none}.input-append .uneditable-input,.input-append input,.input-append select,.input-prepend .uneditable-input,.input-prepend input,.input-prepend select{border-radius:0}.input-mini{width:60px;max-width:100%}.input-small{width:90px;max-width:100%}.input-md,.input-medium{width:150px;max-width:100%}.input-large{width:210px;max-width:100%}.input-xlarge{width:270px;max-width:100%}.input-xxlarge{width:530px;max-width:100%}input.input-lg{font-size:18px}input[type=checkbox].ace,input[type=radio].ace{opacity:0;position:absolute;z-index:1;width:18px;height:18px;cursor:pointer}label input[type=checkbox].ace,label input[type=radio].ace{z-index:-100!important;width:1!important;height:0!important}input[type=checkbox].ace:checked,input[type=checkbox].ace:focus,input[type=radio].ace:checked,input[type=radio].ace:focus{outline:0!important}input[type=checkbox].ace+.lbl,input[type=radio].ace+.lbl{position:relative;display:inline-block;margin:0;line-height:20px;min-height:18px;min-width:18px;font-weight:400;cursor:pointer}input[type=checkbox].ace+.lbl::before,input[type=radio].ace+.lbl::before{cursor:pointer;font-family:fontAwesome;font-weight:400;font-size:12px;color:#32a3ce;content:"\a0";background-color:#FAFAFA;border:1px solid #c8c8c8;box-shadow:0 1px 2px rgba(0,0,0,.05);border-radius:0;display:inline-block;text-align:center;height:16px;line-height:14px;min-width:16px;margin-right:1px;position:relative;top:-1px}input[type=checkbox].ace:checked+.lbl::before,input[type=radio].ace:checked+.lbl::before{display:inline-block;content:'\f00c';background-color:#F5F8FC;border-color:#adb8c0;box-shadow:0 1px 2px rgba(0,0,0,.05),inset 0 -15px 10px -12px rgba(0,0,0,.05),inset 15px 10px -12px rgba(255,255,255,.1)}input[type=checkbox].ace+.lbl:hover::before,input[type=checkbox].ace:hover+.lbl::before,input[type=radio].ace+.lbl:hover::before,input[type=radio].ace:hover+.lbl::before{border-color:#ff893c}input[type=checkbox].ace:active+.lbl::before,input[type=checkbox].ace:checked:active+.lbl::before,input[type=radio].ace:active+.lbl::before,input[type=radio].ace:checked:active+.lbl::before{box-shadow:0 1px 2px rgba(0,0,0,.05),inset 0 1px 3px rgba(0,0,0,.1)}input[type=checkbox].ace.ace-checkbox-2+.lbl::before,input[type=radio].ace.ace-checkbox-2+.lbl::before{box-shadow:none}input[type=checkbox].ace.ace-checkbox-2:checked+.lbl::before,input[type=radio].ace.ace-checkbox-2:checked+.lbl::before{background-color:#f9a021;border-color:#f9a021;color:#FFF}input[type=checkbox].ace.disabled+.lbl::before,input[type=checkbox].ace:disabled+.lbl::before,input[type=checkbox].ace[disabled]+.lbl::before,input[type=radio].ace.disabled+.lbl::before,input[type=radio].ace:disabled+.lbl::before,input[type=radio].ace[disabled]+.lbl::before{background-color:#DDD!important;border-color:#CCC!important;box-shadow:none!important;color:#BBB}input.ace+.lbl.padding-16::before{margin-right:16px}input.ace+.lbl.padding-12::before{margin-right:12px}input.ace+.lbl.padding-8::before{margin-right:8px}input.ace+.lbl.padding-4::before{margin-right:4px}input.ace+.lbl.padding-0::before{margin-right:0}input[type=radio].ace+.lbl::before{border-radius:100%;font-size:10px;font-family:FontAwesome;text-shadow:0 0 1px #32a3ce;line-height:15px;height:17px;min-width:17px}input[type=radio].ace:checked+.lbl::before{content:"\f111"}input[type=checkbox].ace.ace-switch{width:55px;height:25px}input[type=checkbox].ace.ace-switch+.lbl{margin:0 4px;min-height:24px}input[type=checkbox].ace.ace-switch+.lbl::before{font-family:'Open Sans';content:"ON\a0\a0\a0\a0\a0\a0\a0\a0\a0OFF";color:#999;text-shadow:0 0 0 #999;font-weight:400;font-size:11px;line-height:17px;height:20px;overflow:hidden;border-radius:12px;background-color:#F5F5F5;-webkit-box-shadow:inset 0 1px 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 1px 0 rgba(0,0,0,.15);border:1px solid #CCC;text-align:left;float:left;padding:0;width:52px;text-indent:-21px;margin-right:0;-webkit-transition:text-indent .3s ease;-o-transition:text-indent .3s ease;transition:text-indent .3s ease;top:auto}input[type=checkbox].ace.ace-switch+.lbl::after{font-family:'Open Sans';content:'III';font-size:12px;font-weight:400;letter-spacing:0;color:#AAA;text-shadow:none;background-color:#FFF;border-radius:100%;width:22px;height:22px;line-height:22px;text-align:center;position:absolute;top:-2px;left:-3px;-webkit-box-shadow:0 1px 1px 1px rgba(0,0,0,.3);box-shadow:0 1px 1px 1px rgba(0,0,0,.3);-webkit-transition:left .3s ease;-o-transition:left .3s ease;transition:left .3s ease}input[type=checkbox].ace.ace-switch:checked+.lbl::before{text-indent:8px;color:#FFF;text-shadow:0 0 0 #FFF;background-color:#8ab2c9;border-color:#6a8ca8}input[type=checkbox].ace.ace-switch:checked+.lbl::after{left:34px;background-color:#FFF;color:#98A0A5}input[type=checkbox].ace.ace-switch.ace-switch-2+.lbl::before{content:"YES\a0\a0\a0\a0\a0\a0\a0\a0\a0NO"}input[type=checkbox].ace.ace-switch.ace-switch-3+.lbl::after{font-family:FontAwesome;font-size:13px;line-height:22px;content:"\f00d";top:-1px;text-shadow:none;padding:0;text-align:center;color:#BBB;letter-spacing:0}input[type=checkbox].ace.ace-switch.ace-switch-3:checked+.lbl::after{content:"\f00c";color:#8AB2C9;text-shadow:none}input[type=checkbox].ace.ace-switch.ace-switch-4,input[type=checkbox].ace.ace-switch.ace-switch-5{width:60px}input[type=checkbox].ace.ace-switch.ace-switch-4+.lbl::before,input[type=checkbox].ace.ace-switch.ace-switch-5+.lbl::before{content:"ON\a0\a0\a0\a0\a0\a0\a0\a0\a0\a0\a0OFF";font-size:12px;line-height:21px;height:24px;overflow:hidden;border-radius:12px;background-color:#8b9aa3;border:1px solid #8b9aa3;color:#FFF;width:56px;text-shadow:0 0 0 #FFF;display:inline-block;position:relative;box-shadow:none;-webkit-transition:all .3s ease;-o-transition:all .3s ease;transition:all .3s ease}input[type=checkbox].ace.ace-switch.ace-switch-4+.lbl::after,input[type=checkbox].ace.ace-switch.ace-switch-5+.lbl::after{content:'III';font-size:11px;position:absolute;top:2px;left:2px;letter-spacing:0;width:20px;height:20px;line-height:19px;text-shadow:none!important;color:#939393;background-color:#FFF;-webkit-transition:all .3s ease;-o-transition:all .3s ease;transition:all .3s ease}input[type=checkbox].ace.ace-switch.ace-switch-4:checked+.lbl::before,input[type=checkbox].ace.ace-switch.ace-switch-5:checked+.lbl::before{background-color:#468fcc;border-color:#468FCC}input[type=checkbox].ace.ace-switch.ace-switch-4:checked+.lbl::after,input[type=checkbox].ace.ace-switch.ace-switch-5:checked+.lbl::after{left:34px;background-color:#FFF;color:#848484}input[type=checkbox].ace.ace-switch.ace-switch-5+.lbl::before{content:"YES\a0\a0\a0\a0\a0\a0\a0\a0\a0\a0\a0NO"}input[type=checkbox].ace.ace-switch.ace-switch-6+.lbl{position:relative}input[type=checkbox].ace.ace-switch.ace-switch-6+.lbl::before{font-family:FontAwesome;content:"\f00d";text-shadow:0 -1px 0 rgba(0,0,0,.25);box-shadow:none;border-width:0;font-weight:lighter;font-size:16px;border-radius:12px;display:inline-block;background-color:#888;color:#F2F2F2;width:52px;height:22px;line-height:21px;text-indent:32px;-webkit-transition:background .1s ease;-o-transition:background .1s ease;transition:background .1s ease}input[type=checkbox].ace.ace-switch.ace-switch-6+.lbl::after{content:'';text-shadow:0 -1px 0 rgba(0,0,0,.25);position:absolute;top:2px;left:3px;border-radius:12px;box-shadow:0 -1px 0 rgba(0,0,0,.25);width:18px;height:18px;text-align:center;background-color:#F2F2F2;border:4px solid #F2F2F2;-webkit-transition:left .2s ease;-o-transition:left .2s ease;transition:left .2s ease}input[type=checkbox].ace.ace-switch.ace-switch-6:checked+.lbl::before{content:"\f00c";text-indent:6px;color:#FFF;border-color:#b7d3e5;background-color:#ff893c}input[type=checkbox].ace.ace-switch.ace-switch-6:checked+.lbl::after{left:32px;background-color:#FFF;border:4px solid #FFF;text-shadow:0 -1px 0 rgba(0,200,0,.25)}input[type=checkbox].ace.ace-switch.ace-switch-7{width:75px}input[type=checkbox].ace.ace-switch.ace-switch-7+.lbl{position:relative}input[type=checkbox].ace.ace-switch.ace-switch-7+.lbl::before{content:"OFF\a0\a0\a0\a0\a0\a0\a0\a0\a0\a0\a0\a0\a0\a0ON";font-weight:bolder;font-size:13px;background-color:#FFF;border:2px solid #AAA;border-radius:0;box-shadow:none;color:#AAA;width:74px;height:26px;line-height:22px;overflow:hidden;text-indent:5px;display:inline-block;position:relative;-webkit-transition:all .2s ease;-o-transition:all .2s ease;transition:all .2s ease}input[type=checkbox].ace.ace-switch.ace-switch-7+.lbl::after{content:'\f00d';font-family:FontAwesome;font-size:16px;position:absolute;top:3px;left:39px;width:32px;height:20px;line-height:18px;text-align:center;padding:0;text-indent:0;background-color:#AAA;color:#FFF;border-radius:0;box-shadow:none;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}input[type=checkbox].ace.ace-switch.ace-switch-7:checked+.lbl::before{color:#468fcc;background-color:#FFF;text-indent:-28px;border-color:#6fb3e0}input[type=checkbox].ace.ace-switch.ace-switch-7:checked+.lbl::after{left:3px;content:'\f00c';background-color:#468fcc;color:#FFF}input[type=checkbox].ace.ace-switch+.lbl[data-lbl]::before{content:attr(data-lbl)}input[type=checkbox].ace.ace-switch.btn-empty+.lbl::after{content:""}input[type=checkbox].ace.ace-switch.btn-rotate+.lbl::after{content:"\2261";line-height:20px;font-size:17px}input[type=checkbox].ace.ace-switch-4.btn-rotate+.lbl::after,input[type=checkbox].ace.ace-switch-5.btn-rotate+.lbl::after{line-height:17px}input[type=checkbox].ace.ace-switch.btn-flat+.lbl::after,input[type=checkbox].ace.ace-switch.btn-flat+.lbl::before{border-radius:0!important}input[type=checkbox].ace.ace-switch.ace-switch-4+.lbl::before,input[type=checkbox].ace.ace-switch.ace-switch-5+.lbl::before{text-indent:-24px}input[type=checkbox].ace.ace-switch.ace-switch-4:checked+.lbl::before,input[type=checkbox].ace.ace-switch.ace-switch-5:checked+.lbl::before{text-indent:7px}.ace-file-input{display:block;font-size:inherit;position:relative;height:30px}.ace-file-input input[type=file]{position:fixed;z-index:-2;opacity:0;filter:alpha(opacity=0)}.ace-file-input input[type=file]:focus{outline:0}.ace-file-input .ace-file-container{display:block;position:absolute;top:0;left:0;right:0;height:30px;background-color:#fff;border:1px solid #d5d5d5;cursor:pointer;-webkit-box-shadow:none;box-shadow:none;-webkit-transition:all .15s;-o-transition:all .15s;transition:all .15s}.ace-file-input .ace-file-container:hover{-webkit-box-shadow:none;box-shadow:none;border-color:#f59942}.ace-file-input .ace-file-container:before{display:inline-block;content:attr(data-title);position:absolute;right:0;top:0;bottom:0;line-height:24px;text-align:center;padding:0 8px;background-color:#6fb3e0;color:#FFF;font-size:11px;font-weight:700;border:2px solid #FFF;border-left-width:4px;-webkit-transition:all .3s;-o-transition:all .3s;transition:all .3s}.ace-file-input .ace-file-container .ace-file-name{display:inline-block;height:28px;max-width:80%;white-space:nowrap;overflow:hidden;line-height:28px;color:#888;font-size:13px;vertical-align:top;position:static;padding-left:30px}.ace-file-input .ace-file-container .ace-file-name:after{display:inline-block;content:attr(data-title)}.ace-file-input .ace-file-container.selected{right:16px}.ace-file-input .ace-file-container.selected .ace-file-name{color:#666}.ace-file-input .ace-file-container .ace-icon{display:inline-block;position:absolute;left:0;top:0;bottom:0;line-height:24px;width:26px;text-align:center;font-family:FontAwesome;font-size:13px;border:2px solid #FFF;color:#FFF;-webkit-transition:all .1s;-o-transition:all .1s;transition:all .1s;background-color:#d1d1d1}.ace-file-input .ace-file-container.selected .ace-file-name .ace-icon{background-color:#efad62}.ace-file-input .ace-file-container.selected .ace-file-name .file-image{background-color:#bd7a9d}.ace-file-input .ace-file-container.selected .ace-file-name .file-video{background-color:#87b87f}.ace-file-input .ace-file-container.selected .ace-file-name .file-audio{background-color:#8b7ac9}.ace-file-input .ace-file-container.selected .ace-file-name .file-archive{background-color:#efad62}.ace-file-input .ace-file-container.hide-placeholder:before{display:none}.ace-file-input a:hover{text-decoration:none}.ace-file-input .remove{position:absolute;right:-8px;top:6px;display:none;width:17px;text-align:center;height:17px;line-height:15px;font-size:11px;font-weight:400;background-color:#fb7142;border-radius:100%;color:#FFF;text-decoration:none}.ace-file-input .ace-file-container.selected+.remove{display:inline-block}@media screen and (-webkit-min-device-pixel-ratio:0){.ace-file-input input[type=file]{position:absolute;width:0;height:0}}.ace-file-input input[type=file].disabled+.ace-file-container,.ace-file-input input[type=file][disabled]+.ace-file-container,.ace-file-input input[type=file][readonly]+.ace-file-container{cursor:not-allowed;background-color:#EEE}.ace-file-input input[type=file].disabled+.ace-file-container:hover,.ace-file-input input[type=file][disabled]+.ace-file-container:hover,.ace-file-input input[type=file][readonly]+.ace-file-container:hover{-webkit-box-shadow:none;box-shadow:none;border-color:#E3E3E3}.ace-file-input input[type=file].disabled+.ace-file-container:before,.ace-file-input input[type=file][disabled]+.ace-file-container:before,.ace-file-input input[type=file][readonly]+.ace-file-container:before{border-color:#EEE;background-color:#A1AAAF}.ace-file-input input[type=file][readonly]+.ace-file-container{cursor:default}.ace-file-input .ace-file-overlay{position:absolute;top:-2px;bottom:-2px;left:-2px;right:-10px;z-index:99;background-color:rgba(0,0,0,.5)}.ace-file-input .ace-file-overlay>.overlay-content{display:inline-block;position:relative;top:10%;left:0;right:0;text-align:center}.ace-file-multiple{height:auto}.ace-file-multiple .ace-file-container{position:relative;height:auto;border:1px dashed #aaa;border-radius:4px;text-align:center}.ace-file-multiple .ace-file-container:before{display:inline-block;content:attr(data-title);position:relative;right:0;left:0;margin:12px;line-height:22px;background-color:#FFF;color:#CCC;font-size:18px;font-weight:700;border-width:0}.ace-file-multiple .ace-file-container.selected .ace-file-name .ace-icon{display:inline-block;left:0;top:0;bottom:0;width:26px;text-align:center;font-family:FontAwesome;font-size:13px;border:2px solid #FFF;color:#FFF;-webkit-transition:all .1s;-o-transition:all .1s;transition:all .1s}.ace-file-multiple .ace-file-container .ace-file-name{position:relative;display:block;padding:0;height:auto;width:auto;max-width:100%;margin:0 4px;border-bottom:1px solid #DDD;text-align:left}.ace-file-multiple .ace-file-container .ace-file-name:first-child{margin-top:1px}.ace-file-multiple .ace-file-container .ace-file-name:last-child{border-bottom-width:0;margin-bottom:1px}.ace-file-multiple .ace-file-container .ace-file-name img{padding:2px;border:1px solid #D7D7D7;background-color:#FFF;background-repeat:no-repeat;background-position:center;margin:4px 8px 4px 1px}.ace-file-multiple .ace-file-container .ace-file-name:after{display:none}.ace-file-multiple .ace-file-container.selected .ace-file-name:after{display:inline-block;white-space:pre}.ace-file-multiple .ace-file-container .ace-file-name img+.ace-icon,.ace-file-multiple .ace-file-container.selected .ace-file-name img+.ace-icon{display:none}.ace-file-multiple .remove{right:-11px;top:-11px;border:3px solid #BBB;border-radius:32px;background-color:#FFF;color:red;width:23px;height:23px;line-height:15px}.ace-file-multiple .ace-file-container.selected+.remove:hover{border-color:#f4c0b1}.ace-file-multiple .ace-file-overlay{position:absolute;top:-12px;bottom:-6px;left:-12px;right:-12px}.ace-file-multiple .ace-file-overlay>.overlay-content{top:20%}.ace-file-multiple .ace-file-container .ace-file-name .ace-icon{position:relative;display:block;text-align:center;height:auto;line-height:64px;width:auto;font-size:64px;color:#D5D5D5;margin:4px 0;background-color:transparent}.ace-file-multiple .ace-file-container.selected:after{display:none}.ace-file-multiple .ace-file-container.selected .ace-file-name .ace-icon{position:relative;margin-right:4px;margin-left:2px;line-height:24px}.ace-file-multiple .ace-file-container .ace-file-name.large{text-align:center;border-bottom:1px solid #222;margin:0 1px 3px}.ace-file-multiple .ace-file-container .ace-file-name.large:last-child{margin:0 1px}.ace-file-multiple .ace-file-container .ace-file-name.large:after{position:absolute;top:auto;bottom:0;left:0;right:0;padding:0 4px;background-color:#555;color:#FFF;opacity:.8;filter:alpha(opacity=80)}.ace-file-multiple .ace-file-container .ace-file-name.large img{border-width:0;margin:0!important;padding:0}.ace-file-multiple input[type=file].disabled+.ace-file-container:hover,.ace-file-multiple input[type=file][disabled]+.ace-file-container:hover,.ace-file-multiple input[type=file][readonly]+.ace-file-container:hover{border-color:#AAA}.ace-file-multiple input[type=file].disabled+.ace-file-container:before,.ace-file-multiple input[type=file][disabled]+.ace-file-container:before,.ace-file-multiple input[type=file][readonly]+.ace-file-container:before{background-color:transparent}.ace-file-multiple input[type=file].disabled+.ace-file-container .ace-icon,.ace-file-multiple input[type=file][disabled]+.ace-file-container .ace-icon,.ace-file-multiple input[type=file][readonly]+.ace-file-container .ace-icon{border-color:#EEE}.input-group .input-group-addon{border-radius:0!important}.form-group.has-success .input-group .input-group-addon{border-color:#92bf65}.form-group.has-error .input-group .input-group-addon{border-color:#f09784}.form-group.has-warning .input-group .input-group-addon{border-color:#e0c43a}.form-group.has-info .input-group .input-group-addon{border-color:#64a6bc}.input-group>.btn{line-height:20px;padding:0 6px;border-radius:0!important}.input-group>.btn.btn-sm{line-height:22px}.input-group>.btn+.btn{margin-left:1px}.input-group>.btn-group>.btn{line-height:23px}.input-group>.btn-group>.btn.btn-sm{line-height:26px}.input-group>.btn-group>.btn.btn-sm>.caret,.input-group>.btn-group>.btn>.caret,.input-group>.btn.btn-sm>.caret,.input-group>.btn>.caret{margin-top:10px}.input-group.input-group-compact{width:1px}.form-group input[type=color],.form-group input[type=date],.form-group input[type=datetime-local],.form-group input[type=datetime],.form-group input[type=email],.form-group input[type=month],.form-group input[type=number],.form-group input[type=password],.form-group input[type=search],.form-group input[type=tel],.form-group input[type=text],.form-group input[type=time],.form-group input[type=url],.form-group input[type=week],.form-group select,.form-group textarea{background:#FFF}.form-group.has-success input,.form-group.has-success select,.form-group.has-success textarea{border-color:#92bf65;color:#8bad4c;-webkit-box-shadow:none;box-shadow:none}.form-group.has-success input:focus,.form-group.has-success select:focus,.form-group.has-success textarea:focus{-webkit-box-shadow:0 0 0 2px rgba(130,188,58,.3);box-shadow:0 0 0 2px rgba(130,188,58,.3);color:#786;border-color:#81a85a}.form-group.has-success .ace-icon,.form-group.has-success input:focus+.ace-icon,.form-group.has-success select:focus+.ace-icon,.form-group.has-success textarea:focus+.ace-icon{color:#8bad4c}.form-group.has-success .btn .ace-icon{color:inherit}.form-group.has-success .control-label,.form-group.has-success .help-block,.form-group.has-success .help-inline{color:#7ba065}.form-group.has-info input,.form-group.has-info select,.form-group.has-info textarea{border-color:#64a6bc;color:#4b89aa;-webkit-box-shadow:none;box-shadow:none}.form-group.has-info input:focus,.form-group.has-info select:focus,.form-group.has-info textarea:focus{-webkit-box-shadow:0 0 0 2px rgba(58,120,188,.3);box-shadow:0 0 0 2px rgba(58,120,188,.3);color:#678;border-color:#5a81a8}.form-group.has-info .ace-icon,.form-group.has-info input:focus+.ace-icon,.form-group.has-info select:focus+.ace-icon,.form-group.has-info textarea:focus+.ace-icon{color:#4b89aa}.form-group.has-info .btn .ace-icon{color:inherit}.form-group.has-info .control-label,.form-group.has-info .help-block,.form-group.has-info .help-inline{color:#657ba0}.form-group.has-error input,.form-group.has-error select,.form-group.has-error textarea{border-color:#f09784;color:#d68273;-webkit-box-shadow:none;box-shadow:none}.form-group.has-error input:focus,.form-group.has-error select:focus,.form-group.has-error textarea:focus{-webkit-box-shadow:0 0 0 2px rgba(219,137,120,.3);box-shadow:0 0 0 2px rgba(219,137,120,.3);color:#866;border-color:#db8978}.form-group.has-error .ace-icon,.form-group.has-error input:focus+.ace-icon,.form-group.has-error select:focus+.ace-icon,.form-group.has-error textarea:focus+.ace-icon{color:#d68273}.form-group.has-error .btn .ace-icon{color:inherit}.form-group.has-error .control-label,.form-group.has-error .help-block,.form-group.has-error .help-inline{color:#d16e6c}.form-group.has-warning input,.form-group.has-warning select,.form-group.has-warning textarea{border-color:#e0c43a;color:#d3bd50;-webkit-box-shadow:none;box-shadow:none}.form-group.has-warning input:focus,.form-group.has-warning select:focus,.form-group.has-warning textarea:focus{-webkit-box-shadow:0 0 0 2px rgba(216,188,65,.3);box-shadow:0 0 0 2px rgba(216,188,65,.3);color:#875;border-color:#d8bc41}.form-group.has-warning .ace-icon,.form-group.has-warning input:focus+.ace-icon,.form-group.has-warning select:focus+.ace-icon,.form-group.has-warning textarea:focus+.ace-icon{color:#d3bd50}.form-group.has-warning .btn .ace-icon{color:inherit}.form-group.has-warning .control-label,.form-group.has-warning .help-block,.form-group.has-warning .help-inline{color:#d19d59}.form-group input:disabled,.form-group input[disabled]{color:#848484!important;background-color:#eee!important}@media only screen and (max-width:767px){.help-inline,.input-icon+.help-inline{padding-left:0;display:block!important}}.tab-content{border:1px solid #c5d0dc;padding:16px 12px;position:relative}.tab-content.no-padding{padding:0}.tab-content.no-border{border:none;padding:12px}.tab-content.padding-32{padding:32px 24px}.tab-content.no-border.padding-32{padding:32px}.tab-content.padding-30{padding:30px 23px}.tab-content.no-border.padding-30{padding:30px}.tab-content.padding-28{padding:28px 21px}.tab-content.no-border.padding-28{padding:28px}.tab-content.padding-26{padding:26px 20px}.tab-content.no-border.padding-26{padding:26px}.tab-content.padding-24{padding:24px 18px}.tab-content.no-border.padding-24{padding:24px}.tab-content.padding-22{padding:22px 17px}.tab-content.no-border.padding-22{padding:22px}.tab-content.padding-20{padding:20px 15px}.tab-content.no-border.padding-20{padding:20px}.tab-content.padding-18{padding:18px 14px}.tab-content.no-border.padding-18{padding:18px}.tab-content.padding-16{padding:16px 12px}.tab-content.no-border.padding-16{padding:16px}.tab-content.padding-14{padding:14px 11px}.tab-content.no-border.padding-14{padding:14px}.tab-content.padding-12{padding:12px 9px}.tab-content.no-border.padding-12{padding:12px}.tab-content.padding-10{padding:10px 8px}.tab-content.no-border.padding-10{padding:10px}.tab-content.padding-8{padding:8px 6px}.tab-content.no-border.padding-8{padding:8px}.tab-content.padding-6{padding:6px 5px}.tab-content.no-border.padding-6{padding:6px}.tab-content.padding-4{padding:4px 3px}.tab-content.no-border.padding-4{padding:4px}.tab-content.no-border.padding-2,.tab-content.padding-2{padding:2px}.tab-content.no-border.padding-0,.tab-content.padding-0{padding:0}.nav.nav-tabs.padding-32{padding-left:32px}.tabs-left>.nav.nav-tabs.padding-32,.tabs-right>.nav.nav-tabs.padding-32{padding-left:0;padding-top:32px}.nav.nav-tabs.padding-30{padding-left:30px}.tabs-left>.nav.nav-tabs.padding-30,.tabs-right>.nav.nav-tabs.padding-30{padding-left:0;padding-top:30px}.nav.nav-tabs.padding-28{padding-left:28px}.tabs-left>.nav.nav-tabs.padding-28,.tabs-right>.nav.nav-tabs.padding-28{padding-left:0;padding-top:28px}.nav.nav-tabs.padding-26{padding-left:26px}.tabs-left>.nav.nav-tabs.padding-26,.tabs-right>.nav.nav-tabs.padding-26{padding-left:0;padding-top:26px}.nav.nav-tabs.padding-24{padding-left:24px}.tabs-left>.nav.nav-tabs.padding-24,.tabs-right>.nav.nav-tabs.padding-24{padding-left:0;padding-top:24px}.nav.nav-tabs.padding-22{padding-left:22px}.tabs-left>.nav.nav-tabs.padding-22,.tabs-right>.nav.nav-tabs.padding-22{padding-left:0;padding-top:22px}.nav.nav-tabs.padding-20{padding-left:20px}.tabs-left>.nav.nav-tabs.padding-20,.tabs-right>.nav.nav-tabs.padding-20{padding-left:0;padding-top:20px}.nav.nav-tabs.padding-18{padding-left:18px}.tabs-left>.nav.nav-tabs.padding-18,.tabs-right>.nav.nav-tabs.padding-18{padding-left:0;padding-top:18px}.nav.nav-tabs.padding-16{padding-left:16px}.tabs-left>.nav.nav-tabs.padding-16,.tabs-right>.nav.nav-tabs.padding-16{padding-left:0;padding-top:16px}.nav.nav-tabs.padding-14{padding-left:14px}.tabs-left>.nav.nav-tabs.padding-14,.tabs-right>.nav.nav-tabs.padding-14{padding-left:0;padding-top:14px}.nav.nav-tabs.padding-12{padding-left:12px}.tabs-left>.nav.nav-tabs.padding-12,.tabs-right>.nav.nav-tabs.padding-12{padding-left:0;padding-top:12px}.nav.nav-tabs.padding-10{padding-left:10px}.tabs-left>.nav.nav-tabs.padding-10,.tabs-right>.nav.nav-tabs.padding-10{padding-left:0;padding-top:10px}.nav.nav-tabs.padding-8{padding-left:8px}.tabs-left>.nav.nav-tabs.padding-8,.tabs-right>.nav.nav-tabs.padding-8{padding-left:0;padding-top:8px}.nav.nav-tabs.padding-6{padding-left:6px}.tabs-left>.nav.nav-tabs.padding-6,.tabs-right>.nav.nav-tabs.padding-6{padding-left:0;padding-top:6px}.nav.nav-tabs.padding-4{padding-left:4px}.tabs-left>.nav.nav-tabs.padding-4,.tabs-right>.nav.nav-tabs.padding-4{padding-left:0;padding-top:4px}.nav.nav-tabs.padding-2{padding-left:2px}.tabs-left>.nav.nav-tabs.padding-2,.tabs-right>.nav.nav-tabs.padding-2{padding-left:0;padding-top:2px}.nav-tabs{border-color:#C5D0DC;margin-bottom:0!important;margin-left:0;position:relative;top:1px}.nav-tabs>li>a{padding:7px 12px 8px}.nav-tabs>li>a,.nav-tabs>li>a:focus{border-radius:0!important;border-color:#c5d0dc;background-color:#F9F9F9;color:#999;margin-right:-1px;line-height:18px;position:relative}.nav-tabs>li>a:hover{background-color:#FFF;color:#4c8fbd;border-color:#c5d0dc}.nav-tabs>li>a:active,.nav-tabs>li>a:focus{outline:0!important}.nav-tabs>li:first-child>a{margin-left:0}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#576373;border-color:#c5d0dc #c5d0dc transparent;border-top:2px solid #4c8fbd;background-color:#FFF;z-index:1;line-height:18px;margin-top:-1px;box-shadow:0 -2px 3px 0 rgba(0,0,0,.15)}.tabs-below>.nav-tabs{top:auto;margin-bottom:0;margin-top:-1px;border-color:#c5d0dc;border-bottom-width:0}.tabs-below>.nav-tabs>li>a,.tabs-below>.nav-tabs>li>a:focus,.tabs-below>.nav-tabs>li>a:hover{border-color:#c5d0dc}.tabs-below>.nav-tabs>li.active>a,.tabs-below>.nav-tabs>li.active>a:focus,.tabs-below>.nav-tabs>li.active>a:hover{border-color:transparent #c5d0dc #c5d0dc;border-top-width:1px;border-bottom:2px solid #4c8fbd;margin-top:0;box-shadow:0 2px 3px 0 rgba(0,0,0,.15)}.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:60px}.tabs-left>.nav-tabs{top:auto;margin-bottom:0;border-color:#c5d0dc;float:left}.tabs-left>.nav-tabs>li{float:none!important}.tabs-left>.nav-tabs>li>a,.tabs-left>.nav-tabs>li>a:focus,.tabs-left>.nav-tabs>li>a:hover{border-color:#c5d0dc;margin:0 -1px 0 0}.tabs-left>.nav-tabs>li.active>a,.tabs-left>.nav-tabs>li.active>a:focus,.tabs-left>.nav-tabs>li.active>a:hover{border-color:#c5d0dc transparent #c5d0dc #c5d0dc;border-top-width:1px;border-left:2px solid #4c8fbd;margin:0 -1px;-webkit-box-shadow:-2px 0 3px 0 rgba(0,0,0,.15)!important;box-shadow:-2px 0 3px 0 rgba(0,0,0,.15)!important}.tabs-right>.nav-tabs{top:auto;margin-bottom:0;border-color:#c5d0dc;float:right}.tabs-right>.nav-tabs>li{float:none!important}.tabs-right>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a:focus,.tabs-right>.nav-tabs>li>a:hover{border-color:#c5d0dc;margin:0 -1px}.tabs-right>.nav-tabs>li.active>a,.tabs-right>.nav-tabs>li.active>a:focus,.tabs-right>.nav-tabs>li.active>a:hover{border-color:#c5d0dc #c5d0dc #c5d0dc transparent;border-top-width:1px;border-right:2px solid #4c8fbd;margin:0 -2px 0 -1px;-webkit-box-shadow:2px 0 3px 0 rgba(0,0,0,.15);box-shadow:2px 0 3px 0 rgba(0,0,0,.15)}.nav-tabs>li>a>.badge{padding:1px 5px;line-height:15px;opacity:.75}.nav-tabs>li>a>.ace-icon{opacity:.75}.nav-tabs>li.active>a>.ace-icon,.nav-tabs>li.active>a>.badge{opacity:1}.nav-tabs li .ace-icon{width:1.25em;display:inline-block;text-align:center}.nav-tabs>li.open .dropdown-toggle{background-color:#4F99C6;border-color:#4F99C6;color:#FFF}.nav-tabs>li.open .dropdown-toggle>.ace-icon{color:#FFF!important}.tabs-left .tab-content,.tabs-right .tab-content{overflow:auto}.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:focus,.nav>li.dropdown.open.active>a:hover{background-color:#4F99C6;border-color:#4F99C6;color:#FFF}.nav-pills .open .dropdown-toggle>.ace-icon,.nav>li.dropdown.open.active>a:focus>.ace-icon,.nav>li.dropdown.open.active>a:hover>.ace-icon{color:#FFF!important}.nav-tabs>li:not(.active):not(.open)>a:not(:hover)>.ace-icon:first-child.disabled{color:#909090!important}.nav-tabs.tab-size-bigger>li>a{padding-left:14px;padding-right:14px}.nav-tabs.tab-size-bigger>li>a>.ace-icon:first-child{display:block;margin-bottom:6px;width:auto}.nav-tabs.tab-space-1>li>a{margin-right:1px}.nav-tabs.tab-space-2>li>a{margin-right:2px}.nav-tabs.tab-space-3>li>a{margin-right:3px}.nav-tabs.tab-space-4>li>a{margin-right:4px}.nav-tabs[class*=tab-color-]>li>a,.nav-tabs[class*=tab-color-]>li>a:focus,.nav-tabs[class*=tab-color-]>li>a:hover{color:#FFF;border-color:transparent;margin-right:3px}.nav-tabs[class*=tab-color-]>li>a>.badge{border-radius:2px}.nav-tabs[class*=tab-color-]>li:not(.active)>a:hover{opacity:.85;border-color:rgba(0,0,0,.15) rgba(0,0,0,.15) transparent}.nav-tabs[class*=tab-color-]>li:not(.active)>a>.ace-icon:first-child{color:#FFF!important}.nav-tabs[class*=tab-color-]>li:not(.active)>a>.badge{color:rgba(0,0,0,.4)!important;background-color:#FFF!important;border-radius:2px}.nav-tabs.tab-color-blue>li>a,.nav-tabs.tab-color-blue>li>a:focus{background-color:#7db4d8}.nav-tabs[class*=tab-color-]>li.active>a,.nav-tabs[class*=tab-color-]>li.active>a:focus,.nav-tabs[class*=tab-color-]>li.active>a:hover{background-color:#FFF;color:#4f80a0;-webkit-box-shadow:none!important;box-shadow:none!important}.nav-tabs.tab-color-blue>li.active>a,.nav-tabs.tab-color-blue>li.active>a:focus,.nav-tabs.tab-color-blue>li.active>a:hover{color:#4c718a;border-color:#7db4d8 #7db4d8 transparent}.tabs-below .nav-tabs.tab-color-blue>li.active>a{border-color:transparent #7db4d8 #7db4d8}.nav-tabs.tab-color-blue{border-bottom-color:#C5D0DC}.nav-tabs.background-blue{padding-top:6px;background-color:#EFF3F8;border:1px solid #C5D0DC}.tabs-below .nav-tabs.background-blue{padding-top:0;padding-bottom:6px}.tabs-below .nav-tabs.tab-color-blue{border-top:none;border-bottom-color:#C5D0DC}.accordion-style1.panel-group .panel{border-radius:0;border-color:#cdd8e3;background-color:#FFF;box-shadow:none}.accordion-style1.panel-group .panel:last-child{border-bottom-width:1px}.accordion-style1.panel-group .panel .collapse{background-color:#FFF}.accordion-style1.panel-group .panel+.panel{margin-top:2px}.accordion-style1.panel-group .panel-heading+.panel-collapse .panel-body{border-top-color:#cdd8e3!important}.accordion-style1.panel-group .panel-heading{padding:0}.accordion-style1.panel-group .panel-heading .accordion-toggle{color:#4c8fbd;background-color:#eef4f9;position:relative;font-weight:700;font-size:13px;line-height:1;padding:10px;display:block}.accordion-style1.panel-group .panel-heading .accordion-toggle.collapsed{color:#478fca;font-weight:400;background-color:#F9F9F9}.accordion-style1.panel-group .panel-heading .accordion-toggle:hover{color:#6ea6cc;background-color:#f1f8fd;text-decoration:none}.accordion-style1.panel-group .panel-heading .accordion-toggle:active,.accordion-style1.panel-group .panel-heading .accordion-toggle:focus{outline:0;text-decoration:none}.accordion-style1.panel-group .panel-heading .accordion-toggle>.ace-icon:first-child{width:16px}.accordion-style1.panel-group .panel-heading .accordion-toggle:hover>.ace-icon:first-child{text-decoration:none}.accordion-style1.panel-group .collapse.in>.panel-body,.accordion-style1.panel-group .panel-body{border-top:1px solid #cdd8e3}.accordion-style1.panel-group.no-padding{padding:0}.accordion-style2.panel-group .panel{border-width:0}.accordion-style2.panel-group .panel:last-child{border-bottom-width:0}.accordion-style2.panel-group .panel+.panel{margin-top:4px}.accordion-style2.panel-group .panel .panel-body{border-top:none}.accordion-style2.panel-group .panel-heading .accordion-toggle{background-color:#EDF3F7;border:2px solid #6EAED1;border-width:0 0 0 2px}.accordion-style2.panel-group .panel-heading .accordion-toggle:hover{text-decoration:none}.accordion-style2.panel-group .panel-heading .accordion-toggle.collapsed{background-color:#F3F3F3;color:#606060;border-width:0 0 0 1px;border-color:#D9D9D9}.accordion-style2.panel-group .panel-heading .accordion-toggle.collapsed:hover{background-color:#F6F6F6;color:#438EB9;text-decoration:none}.accordion-style2.panel-group .collapse.in>.panel-body,.accordion-style2.panel-group .panel-body{border-top:none}.accordion-style2.panel-group .accordion-style2.panel-group .panel{border-bottom:1px dotted #D9D9D9}.accordion-style2.panel-group .accordion-style2.panel-group .panel:last-child{border-bottom:none}.accordion-style2.panel-group .accordion-style2.panel-group .panel .panel-heading,.accordion-style2.panel-group .accordion-style2.panel-group .panel .panel-heading .accordion-toggle{background-color:transparent;border-width:0;font-size:13px;padding-top:6px;padding-bottom:8px}.accordion-style2.panel-group .accordion-style2.panel-group .panel .panel-heading{padding-top:0;padding-bottom:0}.table-bordered,td,th{border-radius:0!important}.table>thead>tr{color:#707070;font-weight:400;background:#F2F2F2 repeat-x;background-image:-webkit-linear-gradient(top,#f8f8f8 0,#ececec 100%);background-image:-o-linear-gradient(top,#f8f8f8 0,#ececec 100%);background-image:linear-gradient(to bottom,#f8f8f8 0,#ececec 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff8f8f8', endColorstr='#ffececec', GradientType=0)}.table>thead>tr>th{border-color:#ddd;font-weight:700}.table>thead>tr>th .ace-icon:first-child{margin-right:2px}.table>thead>tr>th:first-child{border-left-color:#F1F1F1}.table>thead>tr>th:left-child{border-right-color:#F1F1F1}.table.table-bordered>thead>tr>th{vertical-align:middle}.table.table-bordered>thead>tr>th:first-child{border-left-color:#ddd}td.center,th.center{text-align:center}td .lbl,th .lbl{margin-bottom:0}td .lbl:only-child,th .lbl:only-child{vertical-align:top}.table-header{background-color:#307ecc;color:#FFF;font-size:14px;line-height:38px;padding-left:12px;margin-bottom:1px}.table-header .close{margin-right:8px;margin-top:0;opacity:.45;filter:alpha(opacity=45)}.table-header .close:hover{opacity:.75;filter:alpha(opacity=75)}.widget-box{padding:0;-webkit-box-shadow:none;box-shadow:none;margin:3px 0;border:1px solid #CCC}@media only screen and (max-width:767px){.widget-box{margin-top:7px;margin-bottom:7px}}.widget-header{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;position:relative;min-height:38px;background:#f7f7f7 repeat-x;background-image:-webkit-linear-gradient(top,#fff 0,#eee 100%);background-image:-o-linear-gradient(top,#fff 0,#eee 100%);background-image:linear-gradient(to bottom,#fff 0,#eee 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffeeeeee', GradientType=0);color:#669fc7;border-bottom:1px solid #DDD;padding-left:12px}.widget-header:after,.widget-header:before{content:"";display:table;line-height:0}.widget-header:after{clear:right}.widget-box.collapsed>.widget-header{border-bottom-width:0}.collapsed.fullscreen>.widget-header{border-bottom-width:1px}.collapsed>.widget-body{display:none}.widget-header-flat{background:#F7F7F7;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.widget-header-large{min-height:49px;padding-left:18px}.widget-header-small{min-height:31px;padding-left:10px}.widget-header>.widget-title{line-height:36px;padding:0;margin:0;display:inline}.widget-header>.widget-title>.ace-icon{margin-right:5px;font-weight:400;display:inline-block}.widget-header-large>.widget-title{line-height:48px}.widget-header-small>.widget-title{line-height:30px}.widget-toolbar{display:inline-block;padding:0 10px;line-height:37px;float:right;position:relative}.widget-header-large>.widget-toolbar{line-height:48px}.widget-header-small>.widget-toolbar{line-height:29px}.widget-toolbar.no-padding{padding:0}.widget-toolbar.padding-5{padding:0 5px}.widget-toolbar:before{display:inline-block;content:"";position:absolute;top:3px;bottom:3px;left:-1px;border:1px solid #D9D9D9;border-width:0 1px 0 0}.widget-header-large>.widget-toolbar:before{top:6px;bottom:6px}[class*=widget-color-]>.widget-header>.widget-toolbar:before{border-color:#EEE}.widget-color-orange>.widget-header>.widget-toolbar:before{border-color:#FEA}.widget-color-dark>.widget-header>.widget-toolbar:before{border-color:#222;box-shadow:-1px 0 0 rgba(255,255,255,.2),inset 1px 0 0 rgba(255,255,255,.1)}.widget-toolbar.no-border:before{display:none}.widget-toolbar label{display:inline-block;vertical-align:middle;margin-bottom:0}.widget-toolbar>.widget-menu>a,.widget-toolbar>a{font-size:14px;margin:0 1px;display:inline-block;padding:0;line-height:24px}.widget-toolbar>.widget-menu>a:hover,.widget-toolbar>a:hover{text-decoration:none}.widget-header-large>.widget-toolbar>.widget-menu>a,.widget-header-large>.widget-toolbar>a{font-size:15px;margin:0 1px}.widget-toolbar>.btn{line-height:27px;margin-top:-2px}.widget-toolbar>.btn.smaller{line-height:26px}.widget-toolbar>.btn.bigger{line-height:28px}.widget-toolbar>.btn-sm{line-height:24px}.widget-toolbar>.btn-sm.smaller{line-height:23px}.widget-toolbar>.btn-sm.bigger{line-height:25px}.widget-toolbar>.btn-xs{line-height:22px}.widget-toolbar>.btn-xs.smaller{line-height:21px}.widget-toolbar>.btn-xs.bigger{line-height:23px}.widget-toolbar>.btn-minier{line-height:18px}.widget-toolbar>.btn-minier.smaller{line-height:17px}.widget-toolbar>.btn-minier.bigger{line-height:19px}.widget-toolbar>.btn-lg{line-height:36px}.widget-toolbar>.btn-lg.smaller{line-height:34px}.widget-toolbar>.btn-lg.bigger{line-height:38px}.widget-toolbar-dark{background:#444}.widget-toolbar-light{background:rgba(255,255,255,.85)}.widget-toolbar>.widget-menu{display:inline-block;position:relative}.widget-toolbar>.widget-menu>a[data-action],.widget-toolbar>a[data-action]{-webkit-transition:transform .1s;-o-transition:transform .1s;transition:transform .1s}.widget-toolbar>.widget-menu>a[data-action]>.ace-icon,.widget-toolbar>a[data-action]>.ace-icon{margin-right:0}.widget-toolbar>.widget-menu>a[data-action]:focus,.widget-toolbar>a[data-action]:focus{text-decoration:none;outline:0}.widget-toolbar>.widget-menu>a[data-action]:hover,.widget-toolbar>a[data-action]:hover{-moz-transform:scale(1.2);-webkit-transform:scale(1.2);-o-transform:scale(1.2);-ms-transform:scale(1.2);transform:scale(1.2)}.widget-body{background-color:#FFF}.widget-main{padding:12px}.widget-main.padding-32{padding:32px}.widget-main.padding-30{padding:30px}.widget-main.padding-28{padding:28px}.widget-main.padding-26{padding:26px}.widget-main.padding-24{padding:24px}.widget-main.padding-22{padding:22px}.widget-main.padding-20{padding:20px}.widget-main.padding-18{padding:18px}.widget-main.padding-16{padding:16px}.widget-main.padding-14{padding:14px}.widget-main.padding-12{padding:12px}.widget-main.padding-10{padding:10px}.widget-main.padding-8{padding:8px}.widget-main.padding-6{padding:6px}.widget-main.padding-4{padding:4px}.widget-main.padding-2{padding:2px}.widget-main.no-padding,.widget-main.padding-0{padding:0}.widget-toolbar .progress{vertical-align:middle;display:inline-block;margin:0}.widget-toolbar>.dropdown,.widget-toolbar>.dropup{display:inline-block}.widget-box>.widget-header>.widget-toolbar>.widget-menu>[data-action=settings],.widget-box>.widget-header>.widget-toolbar>[data-action=settings],.widget-color-dark>.widget-header>.widget-toolbar>.widget-menu>[data-action=settings],.widget-color-dark>.widget-header>.widget-toolbar>[data-action=settings]{color:#99CADB}.widget-box>.widget-header>.widget-toolbar>.widget-menu>[data-action=reload],.widget-box>.widget-header>.widget-toolbar>[data-action=reload],.widget-color-dark>.widget-header>.widget-toolbar>.widget-menu>[data-action=reload],.widget-color-dark>.widget-header>.widget-toolbar>[data-action=reload]{color:#ACD392}.widget-box>.widget-header>.widget-toolbar>.widget-menu>[data-action=collapse],.widget-box>.widget-header>.widget-toolbar>[data-action=collapse],.widget-color-dark>.widget-header>.widget-toolbar>.widget-menu>[data-action=collapse],.widget-color-dark>.widget-header>.widget-toolbar>[data-action=collapse]{color:#AAA}.widget-box>.widget-header>.widget-toolbar>.widget-menu>[data-action=close],.widget-box>.widget-header>.widget-toolbar>[data-action=close],.widget-color-dark>.widget-header>.widget-toolbar>.widget-menu>[data-action=close],.widget-color-dark>.widget-header>.widget-toolbar>[data-action=close]{color:#E09E96}.widget-box[class*=widget-color-]>.widget-header{color:#FFF;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.widget-color-blue{border-color:#307ecc}.widget-color-blue>.widget-header{background:#307ecc;border-color:#307ecc}.widget-color-blue2{border-color:#5090c1}.widget-color-blue2>.widget-header{background:#5090c1;border-color:#5090c1}.widget-color-blue3{border-color:#6379aa}.widget-color-blue3>.widget-header{background:#6379aa;border-color:#6379aa}.widget-color-green{border-color:#82af6f}.widget-color-green>.widget-header{background:#82af6f;border-color:#82af6f}.widget-color-green2{border-color:#2e8965}.widget-color-green2>.widget-header{background:#2e8965;border-color:#2e8965}.widget-color-green3{border-color:#4ebc30}.widget-color-green3>.widget-header{background:#4ebc30;border-color:#4ebc30}.widget-color-red{border-color:#e2755f}.widget-color-red>.widget-header{background:#e2755f;border-color:#e2755f}.widget-color-red2{border-color:#e04141}.widget-color-red2>.widget-header{background:#e04141;border-color:#e04141}.widget-color-red3{border-color:#d15b47}.widget-color-red3>.widget-header{background:#d15b47;border-color:#d15b47}.widget-color-purple{border-color:#7e6eb0}.widget-color-purple>.widget-header{background:#7e6eb0;border-color:#7e6eb0}.widget-color-pink{border-color:#ce6f9e}.widget-color-pink>.widget-header{background:#ce6f9e;border-color:#ce6f9e}.widget-color-orange{border-color:#e8b10d}.widget-color-orange>.widget-header{color:#855d10!important;border-color:#e8b10d;background:#ffc657}.widget-color-dark{border-color:#5a5a5a}.widget-color-dark>.widget-header{border-color:#666;background:#404040}.widget-color-grey{border-color:#9e9e9e}.widget-color-grey>.widget-header{border-color:#aaa;background:#848484}.widget-box.transparent{border-width:0}.widget-box.transparent>.widget-header{background:0 0;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);border-width:0;border-bottom:1px solid #DCE8F1;color:#4383B4;padding-left:3px}.widget-box.transparent>.widget-header-large{padding-left:5px}.widget-box.transparent>.widget-header-small{padding-left:1px}.widget-box.transparent>.widget-body{border-width:0;background-color:transparent}[class*=widget-color-]>.widget-header>.widget-toolbar>.widget-menu>[data-action],[class*=widget-color-]>.widget-header>.widget-toolbar>[data-action]{text-shadow:0 1px 1px rgba(0,0,0,.2)}[class*=widget-color-]>.widget-header>.widget-toolbar>.widget-menu>[data-action=settings],[class*=widget-color-]>.widget-header>.widget-toolbar>[data-action=settings]{color:#D3E4ED}[class*=widget-color-]>.widget-header>.widget-toolbar>.widget-menu>[data-action=reload],[class*=widget-color-]>.widget-header>.widget-toolbar>[data-action=reload]{color:#DEEAD3}[class*=widget-color-]>.widget-header>.widget-toolbar>.widget-menu>[data-action=collapse],[class*=widget-color-]>.widget-header>.widget-toolbar>[data-action=collapse]{color:#E2E2E2}[class*=widget-color-]>.widget-header>.widget-toolbar>.widget-menu>[data-action=close],[class*=widget-color-]>.widget-header>.widget-toolbar>[data-action=close]{color:#FFD9D5}.widget-color-orange>.widget-header>.widget-toolbar>.widget-menu>[data-action],.widget-color-orange>.widget-header>.widget-toolbar>[data-action]{text-shadow:none}.widget-color-orange>.widget-header>.widget-toolbar>.widget-menu>[data-action=settings],.widget-color-orange>.widget-header>.widget-toolbar>[data-action=settings]{color:#559AAB}.widget-color-orange>.widget-header>.widget-toolbar>.widget-menu>[data-action=reload],.widget-color-orange>.widget-header>.widget-toolbar>[data-action=reload]{color:#7CA362}.widget-color-orange>.widget-header>.widget-toolbar>.widget-menu>[data-action=collapse],.widget-color-orange>.widget-header>.widget-toolbar>[data-action=collapse]{color:#777}.widget-color-orange>.widget-header>.widget-toolbar>.widget-menu>[data-action=close],.widget-color-orange>.widget-header>.widget-toolbar>[data-action=close]{color:#A05656}.widget-box.light-border[class*=widget-color-]:not(.fullscreen){border-width:0}.widget-box.light-border[class*=widget-color-]:not(.fullscreen)>.widget-header{border:1px solid;border-color:inherit}.widget-box.light-border[class*=widget-color-]:not(.fullscreen)>.widget-body{border:1px solid;border-color:#D6D6D6;border-width:0 1px 1px}.widget-box.no-border{border-width:0}.widget-box.fullscreen{position:fixed;margin:0;top:0;bottom:0;left:0;right:0;background-color:#FFF;border-width:3px;z-index:1040;-moz-backface-visibility:hidden}.widget-box.fullscreen:not([class*=widget-color-]){border-color:#AAA}.widget-body .table{border-top:1px solid #E5E5E5}.widget-body .table thead:first-child tr{background:#FFF}[class*=widget-color-]>.widget-body .table thead:first-child tr{background:#f2f2f2 repeat-x;background-image:-webkit-linear-gradient(top,#f8f8f8 0,#ececec 100%);background-image:-o-linear-gradient(top,#f8f8f8 0,#ececec 100%);background-image:linear-gradient(to bottom,#f8f8f8 0,#ececec 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff8f8f8', endColorstr='#ffececec', GradientType=0)}.widget-body .table.table-bordered thead:first-child>tr{border-top-width:0}.widget-main.no-padding .table{margin-bottom:0;border-width:0}.widget-main.no-padding .table-bordered td:first-child,.widget-main.no-padding .table-bordered th:first-child{border-left-width:0}.transparent>.widget-body .widget-main .table-bordered>tbody>tr>td:last-child,.transparent>.widget-body .widget-main .table-bordered>tfoot>tr>td:last-child,.transparent>.widget-body .widget-main .table-bordered>thead>tr>th:last-child,.widget-main.no-padding .table-bordered>tbody>tr>td:last-child,.widget-main.no-padding .table-bordered>tfoot>tr>td:last-child,.widget-main.no-padding .table-bordered>thead>tr>th:last-child{border-right-width:0!important}.transparent>.widget-body .widget-main .table-bordered>tbody>tr:last-child>td,.widget-main.no-padding .table-bordered>tbody>tr:last-child>td{border-bottom-width:0!important}.table-bordered>thead.thin-border-bottom>tr>td,.table-bordered>thead.thin-border-bottom>tr>th{border-bottom-width:1px}.widget-body .alert:last-child{margin-bottom:0}.widget-main .tab-content{border-width:0}.widget-toolbar>.nav-tabs{border-bottom-width:0;margin-bottom:0;top:auto;margin-top:3px!important}.widget-toolbar>.nav-tabs>li{margin-bottom:auto}.widget-toolbar>.nav-tabs>li>a{box-shadow:none;position:relative;top:1px;margin-top:1px}.widget-toolbar>.nav-tabs>li:not(.active)>a{border-color:transparent;background-color:transparent}.widget-toolbar>.nav-tabs>li:not(.active)>a:hover{background-color:transparent}.widget-toolbar>.nav-tabs>li.active>a{background-color:#FFF;border-bottom-color:transparent;box-shadow:none;margin-top:auto}.widget-header-small>.widget-toolbar>.nav-tabs>li>a{line-height:16px;padding-top:6px;padding-bottom:6px}.widget-header-small>.widget-toolbar>.nav-tabs>li.active>a{border-top-width:2px}.widget-header-large>.widget-toolbar>.nav-tabs>li>a{line-height:22px;padding-top:9px;padding-bottom:9px;margin-top:4px}.widget-header-large>.widget-toolbar>.nav-tabs>li.active>a{margin-top:3px}[class*=widget-color-]>.widget-header>.widget-toolbar>.nav-tabs>li>a{border-color:transparent;background-color:transparent;color:#FFF;margin-right:1px}[class*=widget-color-]>.widget-header>.widget-toolbar>.nav-tabs>li>a:hover{background-color:#FFF;color:#555;border-top-color:#FFF}[class*=widget-color-]>.widget-header>.widget-toolbar>.nav-tabs>li.active>a{background-color:#FFF;color:#555;border-top-width:1px;margin-top:0}.widget-toolbar>.nav-tabs .widget-color-orange>.widget-header>li>a{color:#855D10}.transparent>.widget-header>.widget-toolbar>.nav-tabs>li>a{color:#555;background-color:transparent;border-right:1px solid transparent;border-left:1px solid transparent}.transparent>.widget-header>.widget-toolbar>.nav-tabs>li.active>a{border-top-color:#4C8FBD;border-right:1px solid #C5D0DC;border-left:1px solid #C5D0DC;background-color:#FFF;box-shadow:none}.widget-toolbox{background-color:#EEE}.widget-toolbox:first-child{padding:2px;border-bottom:1px solid #CCC}.widget-toolbox:last-child{padding:2px;border-top:1px solid #CCC}.transparent>.widget-body>.widget-toolbox:last-child{border:none;border-top:1px solid #CCC}.widget-toolbox>.btn-toolbar{margin:0!important;padding:0}.widget-toolbox.center{text-align:center}.widget-toolbox.padding-16{padding:16px}.widget-toolbox.padding-14{padding:14px}.widget-toolbox.padding-12{padding:12px}.widget-toolbox.padding-10{padding:10px}.widget-toolbox.padding-8{padding:8px}.widget-toolbox.padding-6{padding:6px}.widget-toolbox.padding-4{padding:4px}.widget-toolbox.padding-2{padding:2px}.widget-toolbox.padding-0{padding:0}.widget-box-overlay{position:absolute;top:-1px;bottom:-1px;right:-1px;left:-1px;z-index:999;text-align:center;min-height:100%;background-color:rgba(0,0,0,.3)}.widget-box-overlay>.loading-icon{position:relative;top:20%;left:0;right:0;text-align:center}.widget-box.collapsed .widget-box-overlay>.loading-icon{top:10%}.widget-box-overlay>.loading-icon.icon-spin{-moz-animation-duration:1.2s;-webkit-animation-duration:1.2s;-o-animation-duration:1.2s;-ms-animation-duration:1.2s;animation-duration:1.2s}.widget-main>form,.widget-main>form .input-append,.widget-main>form .input-prepend{margin-bottom:0}.widget-main.no-padding>form>fieldset,.widget-main.padding-0>form>fieldset{padding:16px}.widget-main.no-padding>form>fieldset+.form-actions,.widget-main.padding-0>form>fieldset+.form-actions{padding:10px 0 12px}.widget-main.no-padding>form>.form-actions,.widget-main.padding-0>form>.form-actions{margin:0;padding:10px 12px 12px}.widget-placeholder{border:2px dashed #D9D9D9}.tooltip.in{opacity:1;filter:alpha(opacity=100)}.tooltip-inner{background-color:#333;color:#FFF;font-size:12px;text-shadow:1px 1px 0 rgba(42,45,50,.5);border-radius:0;padding:5px 9px}.tooltip.top .tooltip-arrow{border-bottom-width:0;border-top-color:#333;-moz-border-top-colors:#333}.tooltip.right .tooltip-arrow{border-left-width:0;border-right-color:#333;-moz-border-right-colors:#333}.tooltip.left .tooltip-arrow{border-right-width:0;border-left-color:#333;-moz-border-left-colors:#333}.tooltip.bottom .tooltip-arrow{border-top-width:0;border-bottom-color:#333;-moz-border-bottom-colors:#333}.tooltip-error+.tooltip>.tooltip-inner,.tooltip.tooltip-error>.tooltip-inner{background-color:#c94d32;text-shadow:1px 1px 0 rgba(100,60,20,.3)}.tooltip-error+.tooltip.top .tooltip-arrow,.tooltip.tooltip-error.top .tooltip-arrow{border-top-color:#c94d32;-moz-border-top-colors:#c94d32}.tooltip-error+.tooltip.right .tooltip-arrow,.tooltip.tooltip-error.right .tooltip-arrow{border-right-color:#c94d32;-moz-border-right-colors:#c94d32}.tooltip-error+.tooltip.left .tooltip-arrow,.tooltip.tooltip-error.left .tooltip-arrow{border-left-color:#c94d32;-moz-border-left-colors:#c94d32}.tooltip-error+.tooltip.bottom .tooltip-arrow,.tooltip.tooltip-error.bottom .tooltip-arrow{border-bottom-color:#c94d32;-moz-border-bottom-colors:#c94d32}.tooltip-success+.tooltip>.tooltip-inner,.tooltip.tooltip-success>.tooltip-inner{background-color:#629b58;text-shadow:1px 1px 0 rgba(60,100,20,.3)}.tooltip-success+.tooltip.top .tooltip-arrow,.tooltip.tooltip-success.top .tooltip-arrow{border-top-color:#629b58;-moz-border-top-colors:#629b58}.tooltip-success+.tooltip.right .tooltip-arrow,.tooltip.tooltip-success.right .tooltip-arrow{border-right-color:#629b58;-moz-border-right-colors:#629b58}.tooltip-success+.tooltip.left .tooltip-arrow,.tooltip.tooltip-success.left .tooltip-arrow{border-left-color:#629b58;-moz-border-left-colors:#629b58}.tooltip-success+.tooltip.bottom .tooltip-arrow,.tooltip.tooltip-success.bottom .tooltip-arrow{border-bottom-color:#629b58;-moz-border-bottom-colors:#629b58}.tooltip-warning+.tooltip>.tooltip-inner,.tooltip.tooltip-warning>.tooltip-inner{background-color:#ed9421;text-shadow:1px 1px 0 rgba(100,90,10,.3)}.tooltip-warning+.tooltip.top .tooltip-arrow,.tooltip.tooltip-warning.top .tooltip-arrow{border-top-color:#ed9421;-moz-border-top-colors:#ed9421}.tooltip-warning+.tooltip.right .tooltip-arrow,.tooltip.tooltip-warning.right .tooltip-arrow{border-right-color:#ed9421;-moz-border-right-colors:#ed9421}.tooltip-warning+.tooltip.left .tooltip-arrow,.tooltip.tooltip-warning.left .tooltip-arrow{border-left-color:#ed9421;-moz-border-left-colors:#ed9421}.tooltip-warning+.tooltip.bottom .tooltip-arrow,.tooltip.tooltip-warning.bottom .tooltip-arrow{border-bottom-color:#ed9421;-moz-border-bottom-colors:#ed9421}.tooltip-info+.tooltip>.tooltip-inner,.tooltip.tooltip-info>.tooltip-inner{background-color:#4b89aa;text-shadow:1px 1px 0 rgba(40,50,100,.3)}.tooltip-info+.tooltip.top .tooltip-arrow,.tooltip.tooltip-info.top .tooltip-arrow{border-top-color:#4b89aa;-moz-border-top-colors:#4b89aa}.tooltip-info+.tooltip.right .tooltip-arrow,.tooltip.tooltip-info.right .tooltip-arrow{border-right-color:#4b89aa;-moz-border-right-colors:#4b89aa}.tooltip-info+.tooltip.left .tooltip-arrow,.tooltip.tooltip-info.left .tooltip-arrow{border-left-color:#4b89aa;-moz-border-left-colors:#4b89aa}.tooltip-info+.tooltip.bottom .tooltip-arrow,.tooltip.tooltip-info.bottom .tooltip-arrow{border-bottom-color:#4b89aa;-moz-border-bottom-colors:#4b89aa}.popover{border-radius:0;padding:0;border-color:#ccc;border-width:1px;-webkit-box-shadow:0 0 4px 2px rgba(0,0,0,.2);box-shadow:0 0 4px 2px rgba(0,0,0,.2);color:#4D6883}.popover-title{border-radius:0;background-color:#eff3f8;color:#555;border-bottom:1px solid #dde6f0;text-shadow:1px 1px 1px rgba(220,220,220,.2)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;border-bottom-color:#eff3f8;-moz-border-bottom-colors:#eff3f8;border-top-width:0}.popover.left>.arrow:after{-moz-border-left-colors:#FFF}.popover.right>.arrow:after{-moz-border-right-colors:#FFF}.popover.top>.arrow:after{-moz-border-top-colors:#FFF}.popover-error+.popover,.popover.popover-error{border-color:#f7f0ef}.popover-error+.popover .popover-title,.popover.popover-error .popover-title{background-color:#f7f0ef;border-bottom-color:#efe0de;color:#b75445;text-shadow:none}.popover-error+.popover.top .arrow:after,.popover.popover-error.top .arrow:after{border-top-color:#f7f0ef;-moz-border-top-colors:#f7f0ef}.popover-error+.popover.bottom .arrow:after,.popover.popover-error.bottom .arrow:after{border-bottom-color:#f7f0ef;-moz-border-bottom-colors:#f7f0ef}.popover-error+.popover.right .arrow:after,.popover.popover-error.right .arrow:after{border-right-color:#f7f0ef;-moz-border-right-colors:#f7f0ef}.popover-error+.popover.left .arrow:after,.popover.popover-error.left .arrow:after{border-left-color:#f7f0ef;-moz-border-left-colors:#f7f0ef}.popover-warning+.popover,.popover.popover-warning{border-color:#f4eee3}.popover-warning+.popover .popover-title,.popover.popover-warning .popover-title{background-color:#f4eee3;border-bottom-color:#ede3d1;color:#d67e31;text-shadow:none}.popover-warning+.popover.top .arrow:after,.popover.popover-warning.top .arrow:after{border-top-color:#f4eee3;-moz-border-top-colors:#f4eee3}.popover-warning+.popover.bottom .arrow:after,.popover.popover-warning.bottom .arrow:after{border-bottom-color:#f4eee3;-moz-border-bottom-colors:#f4eee3}.popover-warning+.popover.right .arrow:after,.popover.popover-warning.right .arrow:after{border-right-color:#f4eee3;-moz-border-right-colors:#f4eee3}.popover-warning+.popover.left .arrow:after,.popover.popover-warning.left .arrow:after{border-left-color:#f4eee3;-moz-border-left-colors:#f4eee3}.popover-success+.popover,.popover.popover-success{border-color:#e8f2e3}.popover-success+.popover .popover-title,.popover.popover-success .popover-title{background-color:#e8f2e3;border-bottom-color:#daead2;color:#629b58;text-shadow:none}.popover-success+.popover.top .arrow:after,.popover.popover-success.top .arrow:after{border-top-color:#e8f2e3;-moz-border-top-colors:#e8f2e3}.popover-success+.popover.bottom .arrow:after,.popover.popover-success.bottom .arrow:after{border-bottom-color:#e8f2e3;-moz-border-bottom-colors:#e8f2e3}.popover-success+.popover.right .arrow:after,.popover.popover-success.right .arrow:after{border-right-color:#e8f2e3;-moz-border-right-colors:#e8f2e3}.popover-success+.popover.left .arrow:after,.popover.popover-success.left .arrow:after{border-left-color:#e8f2e3;-moz-border-left-colors:#e8f2e3}.popover-info+.popover,.popover.popover-info{border-color:#e5edf8}.popover-info+.popover .popover-title,.popover.popover-info .popover-title{background-color:#e5edf8;border-bottom-color:#d1dff3;color:#3f79b6;text-shadow:none}.popover-info+.popover.top .arrow:after,.popover.popover-info.top .arrow:after{border-top-color:#e5edf8;-moz-border-top-colors:#e5edf8}.popover-info+.popover.bottom .arrow:after,.popover.popover-info.bottom .arrow:after{border-bottom-color:#e5edf8;-moz-border-bottom-colors:#e5edf8}.popover-info+.popover.right .arrow:after,.popover.popover-info.right .arrow:after{border-right-color:#e5edf8;-moz-border-right-colors:#e5edf8}.popover-info+.popover.left .arrow:after,.popover.popover-info.left .arrow:after{border-left-color:#e5edf8;-moz-border-left-colors:#e5edf8}.popover-notitle+.popover .popover-title,.popover.popover-notitle .popover-title{display:none}.popover-notitle+.popover.top .arrow:after,.popover.popover-notitle.top .arrow:after{border-top-color:#FFF;-moz-border-top-colors:#FFF}.popover-notitle+.popover.bottom .arrow:after,.popover.popover-notitle.bottom .arrow:after{border-bottom-color:#FFF;-moz-border-bottom-colors:#FFF}.popover-notitle+.popover.left .arrow:after,.popover.popover-notitle.left .arrow:after{border-left-color:#FFF;-moz-border-left-colors:#FFF}.popover-notitle+.popover.right .arrow:after,.popover.popover-notitle.right .arrow:after{border-right-color:#FFF;-moz-border-right-colors:#FFF}.progress{border-radius:0;-webkit-box-shadow:none;box-shadow:none;background:#dadada;height:18px}.progress .progress-bar{-webkit-box-shadow:none;box-shadow:none;line-height:18px}.progress[data-percent]:after{display:inline-block;content:attr(data-percent);color:#FFF;position:absolute;left:0;right:0;top:0;bottom:0;line-height:16px;text-align:center;font-size:12px}.progress.progress-yellow[data-percent]:after{color:#963}.progress.progress-small{height:12px}.progress.progress-small .progress-bar,.progress.progress-small[data-percent]:after{line-height:10px;font-size:11px}.progress.progress-mini{height:9px}.progress.progress-mini .progress-bar,.progress.progress-mini[data-percent]:after{line-height:8px;font-size:11px}.progress-bar{background-color:#2a91d8}.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#ca5952}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-success{background-color:#59a84b}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f2bb46}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-pink{background-color:#d6487e}.progress-striped .progress-bar-pink{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-purple{background-color:#9585bf}.progress-striped .progress-bar-purple{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-yellow{background-color:#ffd259}.progress-striped .progress-bar-yellow{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-inverse{background-color:#404040}.progress-striped .progress-bar-inverse{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-grey{background-color:#8a8a8a}.progress-striped .progress-bar-grey{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.infobox-container{text-align:center;font-size:0}.infobox{display:inline-block;width:210px;height:66px;color:#555;background-color:#FFF;box-shadow:none;border-radius:0;margin:-1px 0 0 -1px;padding:8px 3px 6px 9px;border:1px dotted;border-color:#D8D8D8!important;vertical-align:middle;text-align:left;position:relative}.infobox>.infobox-icon{display:inline-block;vertical-align:top;width:44px}.infobox>.infobox-icon>.ace-icon{display:inline-block;height:42px;margin:0;padding:1px 1px 0 2px;background-color:transparent;border-width:0;text-align:center;position:relative;border-radius:100%;-webkit-box-shadow:1px 1px 0 rgba(0,0,0,.2);box-shadow:1px 1px 0 rgba(0,0,0,.2)}.infobox>.infobox-icon>.ace-icon:before{font-size:24px;display:block;padding:6px 0 7px;width:40px;text-align:center;border-radius:100%;color:#FFF;color:rgba(255,255,255,.9);background-color:transparent;background-color:rgba(255,255,255,.2);text-shadow:1px 1px 1px rgba(0,0,0,.14)}.infobox .infobox-content{color:#555}.infobox .infobox-content:first-child{font-weight:700}.infobox>.infobox-data{display:inline-block;border-width:0;font-size:13px;text-align:left;line-height:21px;min-width:130px;padding-left:8px;position:relative;top:0}.infobox>.infobox-data>.infobox-data-number{display:block;font-size:22px;margin:2px 0 4px;position:relative;text-shadow:1px 1px 0 rgba(0,0,0,.15)}.infobox>.infobox-data>.infobox-text{display:block;font-size:16px;margin:2px 0 4px;position:relative;text-shadow:none}.infobox.no-border{border-width:0!important}@media only screen and (max-width:479px){.infobox{min-width:95%;margin-top:2px;margin-bottom:2px}}.infobox-purple{color:#6f3cc4;border-color:#6f3cc4}.infobox-purple>.infobox-icon>.ace-icon{background-color:#6f3cc4}.infobox-purple.infobox-dark{background-color:#6f3cc4;border-color:#6f3cc4}.infobox-purple2{color:#5f47b0;border-color:#5f47b0}.infobox-purple2>.infobox-icon>.ace-icon{background-color:#5f47b0}.infobox-purple2.infobox-dark{background-color:#5f47b0;border-color:#5f47b0}.infobox-pink{color:#cb6fd7;border-color:#cb6fd7}.infobox-pink>.infobox-icon>.ace-icon{background-color:#cb6fd7}.infobox-pink.infobox-dark{background-color:#cb6fd7;border-color:#cb6fd7}.infobox-blue{color:#6fb3e0;border-color:#6fb3e0}.infobox-blue>.infobox-icon>.ace-icon{background-color:#6fb3e0}.infobox-blue.infobox-dark{background-color:#6fb3e0;border-color:#6fb3e0}.infobox-blue2{color:#3983c2;border-color:#3983c2}.infobox-blue2>.infobox-icon>.ace-icon{background-color:#3983c2}.infobox-blue2.infobox-dark{background-color:#3983c2;border-color:#3983c2}.infobox-blue3{color:#1144eb;border-color:#1144eb}.infobox-blue3>.infobox-icon>.ace-icon{background-color:#1144eb}.infobox-blue3.infobox-dark{background-color:#1144eb;border-color:#1144eb}.infobox-red{color:#d53f40;border-color:#d53f40}.infobox-red>.infobox-icon>.ace-icon{background-color:#d53f40}.infobox-red.infobox-dark{background-color:#d53f40;border-color:#d53f40}.infobox-brown{color:#c67a3e;border-color:#c67a3e}.infobox-brown>.infobox-icon>.ace-icon{background-color:#c67a3e}.infobox-brown.infobox-dark{background-color:#c67a3e;border-color:#c67a3e}.infobox-wood{color:#7b3f25;border-color:#7b3f25}.infobox-wood>.infobox-icon>.ace-icon{background-color:#7b3f25}.infobox-wood.infobox-dark{background-color:#7b3f25;border-color:#7b3f25}.infobox-light-brown{color:#cebea5;border-color:#cebea5}.infobox-light-brown>.infobox-icon>.ace-icon{background-color:#cebea5}.infobox-light-brown.infobox-dark{background-color:#cebea5;border-color:#cebea5}.infobox-orange{color:#e8b110;border-color:#e8b110}.infobox-orange>.infobox-icon>.ace-icon{background-color:#e8b110}.infobox-orange.infobox-dark{background-color:#e8b110;border-color:#e8b110}.infobox-orange2{color:#f79263;border-color:#f79263}.infobox-orange2>.infobox-icon>.ace-icon{background-color:#f79263}.infobox-orange2.infobox-dark{background-color:#f79263;border-color:#f79263}.infobox-green{color:#9abc32;border-color:#9abc32}.infobox-green>.infobox-icon>.ace-icon{background-color:#9abc32}.infobox-green.infobox-dark{background-color:#9abc32;border-color:#9abc32}.infobox-green2{color:#0490a6;border-color:#0490a6}.infobox-green2>.infobox-icon>.ace-icon{background-color:#0490a6}.infobox-green2.infobox-dark{background-color:#0490a6;border-color:#0490a6}.infobox-grey{color:#999;border-color:#999}.infobox-grey>.infobox-icon>.ace-icon{background-color:#999}.infobox-grey.infobox-dark{background-color:#999;border-color:#999}.infobox-black{color:#393939;border-color:#393939}.infobox-black>.infobox-icon>.ace-icon{background-color:#393939}.infobox-black.infobox-dark{background-color:#393939;border-color:#393939}.infobox-dark{margin:1px 1px 0 0;border-color:transparent!important;border-width:0;color:#FFF;padding:4px}.infobox-dark>.infobox-icon>.ace-icon,.infobox-dark>.infobox-icon>.ace-icon:before{background-color:transparent;box-shadow:none!important;text-shadow:none;border-radius:0;font-size:30px}.infobox-dark>.infobox-icon>.ace-icon:before{opacity:1;filter:alpha(opacity=100)}.infobox-dark .infobox-content{color:#FFF}.infobox>.infobox-progress{padding-top:0;display:inline-block;vertical-align:top;width:44px}.infobox>.infobox-chart{padding-top:0;display:inline-block;vertical-align:text-bottom;width:44px;text-align:center}.infobox>.infobox-chart>.sparkline{font-size:24px}.infobox>.infobox-chart canvas{vertical-align:middle!important}.infobox>.stat{display:inline-block;position:absolute;right:20px;top:11px;text-shadow:none;color:#ABBAC3;font-size:13px;font-weight:700;padding-right:18px;padding-top:3px}.infobox>.stat:before{display:inline-block;content:"";width:8px;height:11px;background-color:#ABBAC3;position:absolute;right:4px;top:7px}.infobox>.stat:after{display:inline-block;content:"";position:absolute;right:1px;top:-8px;border:12px solid transparent;border-width:8px 7px;border-bottom-color:#ABBAC3}.infobox>.stat.stat-success{color:#77C646}.infobox>.stat.stat-success:before{background-color:#77C646}.infobox>.stat.stat-success:after{border-bottom-color:#77C646}.infobox>.stat.stat-important{color:#E4564F}.infobox>.stat.stat-important:before{background-color:#E4564F;top:3px}.infobox>.stat.stat-important:after{border-top-color:#E4564F;border-bottom-color:transparent;bottom:-6px;top:auto}.infobox.infobox-dark>.stat{color:#FFF}.infobox.infobox-dark>.stat:before{background-color:#E1E5E8}.infobox.infobox-dark>.stat:after{border-bottom-color:#E1E5E8}.infobox.infobox-dark>.stat.stat-success{color:#FFF}.infobox.infobox-dark>.stat.stat-success:before{background-color:#D0E29E}.infobox.infobox-dark>.stat.stat-success:after{border-bottom-color:#D0E29E}.infobox.infobox-dark>.stat.stat-important{color:#FFF}.infobox.infobox-dark>.stat.stat-important:before{background-color:#FF8482;top:3px}.infobox.infobox-dark>.stat.stat-important:after{border-top-color:#FF8482;border-bottom-color:transparent;bottom:-6px;top:auto}.infobox>.badge{position:absolute;right:20px;top:11px;border-radius:0;text-shadow:none;color:#FFF;font-size:11px;font-weight:700;line-height:15px;height:16px;padding:0 1px}.infobox.infobox-dark>.badge{color:#FFF;background-color:rgba(255,255,255,.2)!important;border:1px solid #F1F1F1;top:2px;right:2px}.infobox.infobox-dark>.badge.badge-success>.ace-icon{color:#C6E9A1}.infobox.infobox-dark>.badge.badge-important>.ace-icon,.infobox.infobox-dark>.badge.badge-warning>.ace-icon{color:#ECB792}.infobox-small{width:135px;height:52px;text-align:left;padding-bottom:5px}.infobox-small>.infobox-chart,.infobox-small>.infobox-icon,.infobox-small>.infobox-progress{display:inline-block;width:40px;max-width:40px;height:42px;line-height:38px;vertical-align:middle}.infobox-small>.infobox-data{display:inline-block;text-align:left;vertical-align:middle;max-width:72px;min-width:0}.infobox-small>.infobox-chart>.sparkline{font-size:14px;margin-left:2px}.percentage{font-size:14px;font-weight:700;display:inline-block;vertical-align:top}.infobox-small .percentage{font-size:13px;font-weight:400;margin-top:2px;margin-left:2px}.pricing-box:not(:first-child){padding-left:7px}.pricing-box:not(:last-child){padding-right:7px}.pricing-box .price{font-size:22px;line-height:20px;height:28px;text-align:center;color:#555}.pricing-box .price small{font-size:22px}.pricing-box .btn{font-size:16px}.pricing-box .widget-header{text-align:center;padding-left:0}@media only screen and (max-width:480px){.pricing-box{margin:0 0 16px -1px;padding-left:0!important;padding-right:0!important}.pricing-box:nth-child(odd){padding-left:12px!important}.pricing-box:nth-child(even){padding-right:12px!important}}@media only screen and (max-width:479px){.pricing-box{margin:0 0 16px;width:100%;padding-left:12px!important;padding-right:12px!important}}.pricing-table-header{padding-top:0;margin-top:0;text-align:left}.pricing-table-header>li{padding:7px 0 7px 11px;font-size:13px}.pricing-table{margin-top:0}.pricing-table>li{text-align:center;padding:7px 0;font-size:13px}.list-striped>li:nth-child(odd){background-color:#FFF}.list-striped>li:nth-child(even){background-color:#F2F3EB}.list-striped.pricing-table-header>li:nth-child(even){background-color:#EEE}.pricing-box-small{box-shadow:none;margin-left:-2px;background-color:#FFF;position:relative;z-index:10}.pricing-box-small .price{line-height:20px;height:28px;text-align:center}.pricing-box-small .price .label:after,.pricing-box-small .price .label:before{margin-top:-2px;opacity:.9;filter:alpha(opacity=90)}.pricing-box-small:hover{box-shadow:0 0 4px 2px rgba(0,0,0,.15);z-index:11;-webkit-transform:scale(1.04);-ms-transform:scale(1.04);-o-transform:scale(1.04);transform:scale(1.04)}.pricing-box-small:hover .price>.label{-webkit-transform:scale(0.96);-ms-transform:scale(0.96);-o-transform:scale(0.96);transform:scale(0.96)}.pricing-span{margin:0;width:19%;max-width:150px!important;min-width:110px!important;float:left!important}.pricing-span-header{padding-right:0}@media only screen and (min-width:480px){.pricing-span-body{padding-left:0;padding-right:0}}@media only screen and (max-width:480px){.pricing-span-body,.pricing-span-header{width:100%;padding-right:12px}}.login-container{width:375px;margin:0 auto}.login-layout{background-color:#1D2024}.login-layout .main-container:before{display:none}.login-layout .main-content{margin-left:0!important;margin-right:0!important;min-height:100%;padding-left:15px;padding-right:15px}.login-layout label{margin-bottom:11px}.login-layout .widget-box{visibility:hidden;position:fixed;z-index:-5;border-bottom:none;box-shadow:none;padding:6px;background-color:#394557;-moz-transform:scale(0,1) translate(-150px);-webkit-transform:scale(0,1) translate(-150px);-o-transform:scale(0,1) translate(-150px);-ms-transform:scale(0,1) translate(-150px);transform:scale(0,1) translate(-150px)}.login-layout .widget-box.visible{visibility:visible;position:relative;z-index:auto;-moz-transform:scale(1,1) translate(0);-webkit-transform:scale(1,1) translate(0);-o-transform:scale(1,1) translate(0);-ms-transform:scale(1,1) translate(0);transform:scale(1,1) translate(0);transition:transform .3s ease;-moz-transition:-moz-transform .3s ease;-webkit-transition:-webkit-transform .3s ease;-o-transition:-o-transform .2s ease}.login-layout .widget-box .widget-main{padding:16px 36px 36px;background:#F7F7F7}.login-layout .widget-box .widget-main form{margin:0}.login-layout .widget-box .widget-body .toolbar>div>a{font-size:15px;font-weight:400;text-shadow:1px 0 1px rgba(0,0,0,.25)}.login-box .forgot-password-link{color:#FE9}.login-box .user-signup-link{color:#CF7}.login-box .toolbar{background:#5090C1;border-top:2px solid #597597}.login-box .toolbar>div{width:50%;display:inline-block;padding:9px 0 11px}.login-box .toolbar>div:first-child{float:left;text-align:left}.login-box .toolbar>div:first-child>a{margin-left:11px}.login-box .toolbar>div:first-child+div{float:right;text-align:right}.login-box .toolbar>div:first-child+div>a{margin-right:11px}.forgot-box .toolbar{background:#C16050;border-top:2px solid #976559;padding:9px 18px}.signup-box .toolbar{background:#76B774;border-top:2px solid #759759;padding:9px 18px}.forgot-box .back-to-login-link,.signup-box .back-to-login-link{color:#FE9;font-size:14px;font-weight:700;text-shadow:1px 0 1px rgba(0,0,0,.25)}.login-layout .login-box .widget-main{padding-bottom:16px}.social-or-login{margin-top:4px;text-align:center;position:relative;z-index:1}.social-or-login :first-child{display:inline-block;background:#F7F7F7;padding:0 8px;color:#5090C1;font-size:13px}.social-or-login:before{content:"";display:block;position:absolute;z-index:-1;top:50%;left:0;right:0;border-top:1px dotted #A6C4DB}.social-login a{border-radius:100%;width:42px;height:42px;line-height:46px;padding:0;margin:0 1px;border-width:0}.social-login a>.ace-icon{font-size:24px;margin:0}@media only screen and (max-width:540px){.login-layout .widget-box .widget-main{padding:16px}.login-container{width:98%}.login-layout .widget-box{padding:0}.login-layout .main-content{padding-left:6px;padding-right:6px}.login-box .toolbar>div{width:auto}}.light-login{background:#dfe0e2 url(images/pattern.jpg)}.light-login .widget-box{padding:1px 1px 0;-webkit-box-shadow:0 0 2px 1px rgba(0,0,0,.12);box-shadow:0 0 2px 1px rgba(0,0,0,.12);border-bottom:1px solid rgba(50,50,50,.33)}.light-login .widget-box .toolbar{border-top-width:1px}.light-login .widget-box.login-box{background-color:#BCC6CF;background-color:rgba(100,110,120,.4)}.light-login .widget-box.signup-box{background-color:#C1CEC4;background-color:rgba(110,120,100,.4)}.light-login .widget-box.forgot-box{background-color:#D2C5C5;background-color:rgba(120,110,100,.4)}.blur-login{background:#394557 url(images/meteorshower2.jpg)}.invoice-info{line-height:24px!important;color:#444;vertical-align:bottom;margin-left:9px;margin-right:9px}.invoice-info-label{display:inline-block;max-width:100px;text-align:right;font-size:14px}.invoice-box .label-large[class*=arrowed]{margin-left:11px!important;max-width:95%}.error-container{margin:20px;padding:0;background:#FFF}@media only screen and (max-width:767px){.error-container{margin:12px}}@media only screen and (max-width:479px){.error-container{margin:6px}}.ace-thumbnails{list-style:none;margin:0;padding:0}.ace-thumbnails>li{float:left;display:block;position:relative;overflow:hidden;margin:2px;border:2px solid #333}.ace-thumbnails>li>:first-child{display:block;position:relative}.ace-thumbnails>li>:first-child:focus{outline:0}.ace-thumbnails>li .tags{display:inline-block;position:absolute;bottom:0;right:0;overflow:visible;direction:rtl;padding:0;margin:0;height:auto;width:auto;background-color:transparent;border-width:0;vertical-align:inherit}.ace-thumbnails>li .tags>.label-holder{opacity:.92;filter:alpha(opacity=92);display:table;margin:1px 0 0;direction:ltr;text-align:left}.ace-thumbnails>li .tags>.label-holder:hover{opacity:1;filter:alpha(opacity=100)}.ace-thumbnails>li>.tools{position:absolute;top:0;bottom:0;left:-30px;width:24px;background-color:rgba(0,0,0,.55);text-align:center;vertical-align:middle;-webkit-transition:all .2s ease;-o-transition:all .2s ease;transition:all .2s ease}.ace-thumbnails>li>.tools.tools-right{left:auto;right:-30px}.ace-thumbnails>li>.tools.tools-bottom{width:auto;height:28px;left:0;right:0;top:auto;bottom:-30px}.ace-thumbnails>li>.tools.tools-top{width:auto;height:28px;left:0;right:0;top:-30px;bottom:auto}.ace-thumbnails>li:hover>.tools{left:0;right:0}.ace-thumbnails>li:hover>.tools.tools-bottom{top:auto;bottom:0}.ace-thumbnails>li:hover>.tools.tools-top{bottom:auto;top:0}.ace-thumbnails>li:hover>.tools.tools-right{left:auto;right:0}.ace-thumbnails>li>.in.tools{left:0;right:0}.ace-thumbnails>li>.in.tools.tools-bottom{top:auto;bottom:0}.ace-thumbnails>li>.in.tools.tools-top{bottom:auto;top:0}.ace-thumbnails>li>.in.tools.tools-right{left:auto;right:0}.ace-thumbnails>li>.tools>a,.ace-thumbnails>li>:first-child .inner a{display:inline-block;color:#FFF;font-size:18px;font-weight:400;padding:0 4px}.ace-thumbnails>li>.tools>a:hover,.ace-thumbnails>li>:first-child .inner a:hover{text-decoration:none;color:#C9E2EA}.ace-thumbnails>li .tools.tools-bottom>a,.ace-thumbnails>li .tools.tools-top>a{display:inline-block}.ace-thumbnails>li>:first-child>.text{position:absolute;right:0;left:0;bottom:0;top:0;text-align:center;color:#FFF;background-color:rgba(0,0,0,.55);opacity:0;filter:alpha(opacity=0);-webkit-transition:all .2s ease;-o-transition:all .2s ease;transition:all .2s ease}.ace-thumbnails>li>:first-child>.text:before{content:'';display:inline-block;height:100%;vertical-align:middle;margin-right:0}.ace-thumbnails>li>:first-child>.text>.inner{padding:4px 0;margin:0;display:inline-block;vertical-align:middle;max-width:90%}.ace-thumbnails>li:hover>:first-child>.text{opacity:1;filter:alpha(opacity=100)}@media only screen and (max-width:480px){.ace-thumbnails{text-align:center}.ace-thumbnails>li{float:none;display:inline-block}}.dialogs{padding:9px;position:relative}.itemdiv{padding-right:3px;min-height:66px;position:relative}.itemdiv>.user{display:inline-block;width:42px;position:absolute;left:0}.itemdiv>.user>img{border-radius:100%;border:2px solid #5293C4;max-width:40px;position:relative}.itemdiv>.body{width:auto;margin-left:50px;margin-right:12px;position:relative}.itemdiv>.body>.time{display:block;font-size:11px;font-weight:700;color:#666;position:absolute;right:9px;top:0}.itemdiv>.body>.time .ace-icon{font-size:14px;font-weight:400}.itemdiv>.body>.name{display:block;color:#999}.itemdiv>.body>.name>b{color:#777}.itemdiv>.body>.text{display:block;position:relative;margin-top:2px;padding-bottom:19px;padding-left:7px;font-size:13px}.itemdiv>.body>.text:after{display:block;content:"";height:1px;font-size:0;overflow:hidden;position:absolute;left:16px;right:-12px;margin-top:9px;border-top:1px solid #E4ECF3}.itemdiv>.body>.text>.ace-icon:first-child{color:#DCE3ED;margin-right:4px}.itemdiv:last-child>.body>.text{border-bottom-width:0}.itemdiv:last-child>.body>.text:after{display:none}.itemdiv.dialogdiv{padding-bottom:14px}.itemdiv.dialogdiv:before{position:absolute;display:block;content:"";top:0;bottom:0;left:19px;width:3px;max-width:3px;background-color:#E1E6ED;border:1px solid #D7DBDD;border-width:0 1px}.itemdiv.dialogdiv:last-child{padding-bottom:0}.itemdiv.dialogdiv:last-child:before{display:none}.itemdiv.dialogdiv>.user>img{border-color:#C9D6E5}.itemdiv.dialogdiv>.body{border:1px solid #DDE4ED;padding:5px 8px 8px;border-left-width:2px;margin-right:1px}.itemdiv.dialogdiv>.body:before{content:"";display:block;position:absolute;left:-7px;top:11px;width:8px;height:8px;border:2px solid #DDE4ED;border-width:2px 0 0 2px;background-color:#FFF;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-transform:rotate(-45deg);-ms-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg)}.itemdiv.dialogdiv>.body>.time{position:static;float:right}.itemdiv.dialogdiv>.body>.text{padding-left:0;padding-bottom:0}.itemdiv.dialogdiv>.body>.text:after{display:none}.itemdiv.dialogdiv .tooltip-inner{word-break:break-all}.itemdiv.memberdiv{width:175px;padding:2px;margin:3px 0;float:left;border-bottom:1px solid #E8E8E8}@media (min-width:992px){.itemdiv.memberdiv{max-width:50%}}@media (max-width:991px){.itemdiv.memberdiv{min-width:33.333%}}.itemdiv.memberdiv>.user>img{border-color:#DCE3ED}.itemdiv.memberdiv>.body>.time{position:static}.itemdiv.memberdiv>.body>.name{line-height:18px;height:18px;margin-bottom:0}.itemdiv.memberdiv>.body>.name>a{display:inline-block;max-width:100px;max-height:18px;overflow:hidden;text-overflow:ellipsis;word-break:break-all}.itemdiv .tools{position:absolute;right:5px;bottom:10px;display:none}.itemdiv .tools .btn{border-radius:36px;margin:1px 0}.itemdiv .body .tools{bottom:4px}.itemdiv.commentdiv .tools{right:9px}.itemdiv:hover .tools{display:inline-block}.item-list{margin:0;padding:0;list-style:none}.item-list>li{padding:9px;background-color:#FFF;margin-top:-1px;position:relative}.item-list>li.selected{color:#8090A0;background-color:#F4F9FC}.item-list>li.selected .lbl,.item-list>li.selected label{text-decoration:line-through;color:#8090A0}.item-list>li>.checkbox,.item-list>li>label.inline{display:inline-block}.item-list>li label{font-size:13px}.item-list>li .percentage{font-size:11px;font-weight:700;color:#777}.item-list>li.ui-sortable-helper{cursor:move}li[class*=item-]{border:1px solid #DDD;border-left-width:3px}li.item-orange{border-left-color:#e8b110}li.item-orange2{border-left-color:#f79263}li.item-red{border-left-color:#d53f40}li.item-red2{border-left-color:#d15b47}li.item-green{border-left-color:#9abc32}li.item-green2{border-left-color:#0490a6}li.item-blue{border-left-color:#4f99c6}li.item-blue2{border-left-color:#3983c2}li.item-blue3{border-left-color:#1144eb}li.item-pink{border-left-color:#cb6fd7}li.item-purple{border-left-color:#6f3cc4}li.item-black{border-left-color:#505050}li.item-grey{border-left-color:#a0a0a0}li.item-brown{border-left-color:brown}li.item-default{border-left-color:#abbac3}.ui-sortable-helper,.ui-sortable-helper>a,.ui-sortable-placeholder,.ui-sortable-placeholder>a{cursor:move!important}@media only screen and (max-width:480px){.itemdiv.memberdiv{float:none;width:auto}}.profile-user-info{display:table;width:98%;width:calc(100% - 24px);margin:0 auto}.profile-info-row{display:table-row}.profile-info-name{text-align:right;padding:6px 10px 6px 4px;font-weight:400;color:#667E99;background-color:transparent;border-top:1px dotted #D5E4F1;display:table-cell;width:110px;vertical-align:middle}.profile-info-value{display:table-cell;padding:6px 4px 6px 6px;border-top:1px dotted #D5E4F1}.profile-info-value>span+span:before{display:inline;content:",";margin-left:1px;margin-right:3px;color:#666;border-bottom:1px solid #FFF}.profile-info-value>span+span.editable-container:before{display:none}.profile-info-row:first-child .profile-info-name,.profile-info-row:first-child .profile-info-value{border-top:none}.profile-user-info-striped{border:1px solid #DCEBF7}.profile-user-info-striped .profile-info-name{color:#336199;background-color:#EDF3F4;border-top:1px solid #F7FBFF}.profile-user-info-striped .profile-info-value{border-top:1px dotted #DCEBF7;padding-left:12px}.profile-picture{border:1px solid #CCC;background-color:#FFF;padding:4px;display:inline-block;max-width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;box-shadow:1px 1px 1px rgba(0,0,0,.15)}.profile-activity{padding:10px 4px;border-bottom:1px dotted #D0D8E0;position:relative;border-left:1px dotted #FFF;border-right:1px dotted #FFF}.profile-activity:first-child{border-top:1px dotted transparent}.profile-activity:first-child:hover{border-top-color:#D0D8E0}.profile-activity:hover{background-color:#F4F9FD;border-left:1px dotted #D0D8E0;border-right:1px dotted #D0D8E0}.profile-activity img{border:2px solid #C9D6E5;border-radius:100%;max-width:40px;margin-right:10px;margin-left:0;box-shadow:none}.profile-activity .thumbicon{background-color:#74ABD7;display:inline-block;border-radius:100%;width:38px;height:38px;color:#FFF;font-size:18px;text-align:center;line-height:38px;margin-right:10px;margin-left:0;text-shadow:none!important}.profile-activity .time{display:block;margin-top:4px;color:#777}.profile-activity a.user{font-weight:700;color:#9585BF}.profile-activity .tools{position:absolute;right:12px;bottom:8px;display:none}.profile-activity:hover .tools{display:block}.user-profile .ace-thumbnails li{border:1px solid #CCC;padding:3px;margin:6px}.user-profile .ace-thumbnails li .tools{left:3px;right:3px}.user-profile .ace-thumbnails li:hover .tools{bottom:3px}.user-profile .user-title-label:hover{text-decoration:none}.user-profile .user-title-label+.dropdown-menu{margin-left:-12px}.profile-contact-links{padding:4px 2px 5px;border:1px solid #E0E2E5;background-color:#F8FAFC}.btn-link:hover .ace-icon{text-decoration:none!important}.profile-social-links>a{text-decoration:none;margin:0 1px}.profile-social-links>a:hover>.ace-icon{text-decoration:none}.profile-skills .progress{height:26px;margin-bottom:2px;background-color:transparent}.profile-skills .progress .progress-bar{line-height:26px;font-size:13px;font-weight:700;font-family:"Open Sans";padding:0 8px}.profile-users .user{display:block;position:static;text-align:center;width:auto}.profile-users .user img{padding:2px;border-radius:100%;border:1px solid #AAA;max-width:none;width:64px;-webkit-transition:all .1s;-o-transition:all .1s;transition:all .1s}.profile-users .user img:hover{-webkit-box-shadow:0 0 1px 1px rgba(0,0,0,.33);box-shadow:0 0 1px 1px rgba(0,0,0,.33)}.profile-users .memberdiv{background-color:#FFF;width:100px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border:none;text-align:center;margin:0 8px 24px}.profile-users .memberdiv .name a:hover .ace-icon{text-decoration:none}.profile-users .memberdiv .body{display:inline-block;margin:8px 0 0}.profile-users .memberdiv .popover{visibility:hidden;min-width:0;max-height:0;max-width:0;margin-left:0;margin-right:0;top:-5%;left:auto;right:auto;opacity:0;display:none;position:absolute;-webkit-transition:opacity .2s linear 0s,visibility 0s linear .2s,max-height 0s linear .2s,max-width 0s linear .2s,min-width 0s linear .2s;-o-transition:opacity .2s linear 0s,visibility 0s linear .2s,max-height 0s linear .2s,max-width 0s linear .2s,min-width 0s linear .2s;transition:opacity .2s linear 0s,visibility 0s linear .2s,max-height 0s linear .2s,max-width 0s linear .2s,min-width 0s linear .2s}.profile-users .memberdiv .popover.right{left:100%;right:auto;display:block}.profile-users .memberdiv .popover.left{left:auto;right:100%;display:block}.profile-users .memberdiv>:first-child:hover .popover{visibility:visible;opacity:1;z-index:1060;max-height:250px;max-width:250px;min-width:150px;-webkit-transition-delay:0s;-moz-transition-delay:0s;-o-transition-delay:0s;transition-delay:0s}.profile-users .memberdiv .tools{position:static;display:block;width:100%;margin-top:2px}.profile-users .memberdiv .tools>a{margin:0 2px}.profile-users .memberdiv .tools>a:hover{text-decoration:none}.user-status{display:inline-block;width:11px;height:11px;background-color:#FFF;border:3px solid #AAA;border-radius:100%;vertical-align:middle;margin-right:1px}.user-status.status-online{border-color:#8AC16C}.user-status.status-busy{border-color:#E07F69}.user-status.status-idle{border-color:#FFB752}.tab-content.profile-edit-tab-content{border:1px solid #DDD;padding:8px 32px 32px;-webkit-box-shadow:1px 1px 0 0 rgba(0,0,0,.2);box-shadow:1px 1px 0 0 rgba(0,0,0,.2);background-color:#FFF}@media only screen and (max-width:480px){.profile-info-name{width:80px}.profile-user-info-striped .profile-info-name{float:none;width:auto;text-align:left;padding:6px 4px 6px 10px;display:block}.profile-user-info-striped .profile-info-value{margin-left:10px;display:block}}@media only screen and (max-width:480px){.user-profile .memberdiv{width:50%;margin-left:0;margin-right:0}}.inbox-tabs.nav-tabs>li>a{background-color:#FAFAFA}.inbox-tabs.nav-tabs>li.active:not(.open)>a,.inbox-tabs.nav-tabs>li.active:not(.open)>a:focus,.inbox-tabs.nav-tabs>li.active:not(.open)>a:hover{background-color:#F1F5FA;box-shadow:0 -2px 3px 0 rgba(0,0,0,.1);color:#48768E}.inbox-tabs.nav-tabs>li>a.btn-new-mail{background-color:transparent;border:none!important;padding:0!important}.inbox-tabs.nav-tabs>li>a.btn-new-mail>.btn{border-width:0!important;border-radius:3px!important;padding:0 6px!important;position:relative;transition:none!important}.inbox-tabs.nav-tabs>li.active>a.btn-new-mail{box-shadow:none!important}.inbox-tabs.nav-tabs>li.active>a.btn-new-mail>.btn:before{content:"";display:block;position:absolute;top:100%;left:50%;margin-left:-6px;border-width:6px 8px;border-style:solid;border-color:transparent;border-top-color:inherit}.inbox-tabs.nav-tabs.tab-size-bigger>li>a{padding:5px 15px 7px;font-size:14px}.inbox-tabs.nav-tabs.tab-size-bigger>li>a>.ace-icon:first-child{margin-bottom:5px}.inbox-tabs.nav-tabs.tab-size-bigger>li>a.btn-new-mail>.btn{padding:10px!important;border-radius:7px!important}.inbox-tabs.nav-tabs.tab-size-bigger>li.active>a.btn-new-mail{margin-top:0!important;top:1px}.inbox-tabs.nav-tabs.tab-size-bigger>li.active>a.btn-new-mail>.btn:before{left:50%;margin-left:-8px;border-width:8px 10px}@media only screen and (max-width:479px){.inbox-tabs>.li-new-mail{display:block;text-align:right;margin-bottom:8px!important;float:none!important}.inbox-tabs>.li-new-mail>.btn-new-mail{display:inline-block;width:auto}}.message-container,.message-list{position:relative}.message-item{border:1px solid #EAEDF1;border-bottom-width:0;padding:12px 12px 14px;line-height:18px;position:relative;background-color:#FFF}.message-item:first-child{border-top-width:0}.message-item:hover{border-color:#E2EAF2;background-color:#F2F6F9}.message-item:hover+.message-item{border-top-color:#E2EAF2}.message-item:hover+.message-item.selected{border-top-color:#FFF}.message-item.selected{background-color:#EFF4F7;border-color:#FFF #E2EAF2}.message-item.selected+.message-item,.message-item.selected+.message-item:hover+.message-item{border-top-color:#FFF}.message-item input.ace+.lbl::before,.message-navbar input.ace+.lbl::before{top:auto}.message-item .sender{margin:0 6px 0 4px;vertical-align:middle;color:#467287;display:inline-block;width:110px;height:18px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;cursor:pointer}.message-item.message-unread .sender{color:#6A9CBA;font-weight:700}.message-item .summary{vertical-align:middle;display:inline-block;position:relative;margin-left:30px;max-width:250px;max-width:calc(100% - 300px);min-width:200px;white-space:nowrap}.message-item .summary .text{color:#555;vertical-align:middle;display:inline-block;width:auto;max-width:100%;height:18px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;cursor:pointer}.message-item .summary .text:hover{text-decoration:underline}.message-item .summary .message-flags{display:block;position:absolute;right:100%;margin-right:4px;height:18px;white-space:nowrap}.message-item.message-unread .summary .text{color:#609FC4;font-weight:700}.message-item .time{float:right;width:60px;height:18px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;color:#666}.message-item.message-unread .time{font-weight:700;color:#609FC4}.message-item.message-unread .message-content .time{font-weight:400}.message-item .attachment{color:#999;font-size:18px;vertical-align:middle;float:right;margin:0 12px;position:relative}.message-item.message-unread .attachment{color:#4F99C6}.message-content .time{font-weight:400}.message-star{vertical-align:middle;margin:2px 4px 0 6px;font-size:15px;cursor:pointer}.message-star:hover{color:#feb902!important;text-decoration:none}.mail-tag:empty{display:inline-block;width:8px;height:11px;padding:0;line-height:normal;vertical-align:middle;margin:0 1px 0 0}.badge.mail-tag{border-radius:2px}.dropdown-menu>li>a>.mail-tag{vertical-align:inherit}@media only screen and (max-width:991px){.message-item .summary{min-width:0}.message-item .sender{width:100px}}@media only screen and (max-width:550px){.message-item .summary{margin:8px 0 0 32px;max-width:95%;min-width:0;display:block}.message-item .sender{width:auto;max-width:150px}.message-item .summary .text{max-width:95%}}.btn-message,.btn-message:active,.btn-message:focus,.btn-message:hover,.open .btn-message.dropdown-toggle{background-color:#FFF!important;border:1px solid #94B9CE!important;color:#7CA3BA!important;text-shadow:none!important}.message-content{padding:16px 12px;border:1px solid #E9E9E9;-webkit-box-shadow:0 0 1px 1px rgba(0,0,0,.02);box-shadow:0 0 1px 1px rgba(0,0,0,.02);background-color:rgba(255,255,255,.8);border-top-width:0}.message-item .message-content{margin-top:16px;border-top-width:1px}.message-body{padding:0 9px;color:#6A7177}.message-navbar{line-height:24px;padding:10px 12px;border:1px solid #D6E1EA;border-color:#D6E1EA transparent;background-color:#F1F5FA;text-align:center;position:relative}.message-content .dropdown-toggle,.message-navbar .dropdown-toggle{color:#777}.message-content .dropdown-toggle:focus,.message-content .dropdown-toggle:hover,.message-navbar .dropdown-toggle:focus,.message-navbar .dropdown-toggle:hover{text-decoration:none;color:#2283C5}.message-bar{display:inline-block;min-height:28px}@media only screen and (max-width:480px){.message-bar{display:block;min-height:60px}}.message-footer{background-color:#F1F1F1;padding:12px 16px;border:1px solid #E6E6E6;border-width:1px 0;border-top:1px solid #E4E9EE}.message-footer .pagination{margin:0}.message-footer .pagination>li{margin:0;padding:0}.message-footer .pagination>li>a,.message-footer .pagination>li>span{color:#777;padding:3px 6px;margin-left:1px;margin-right:1px;background-color:transparent;border:1px solid transparent}.message-footer .pagination>li.disabled>span{color:#BBB;cursor:default;background-color:transparent;border-color:transparent}.message-footer .pagination>li>a:hover{border-color:#91bad6;color:#2283C5;text-decoration:none;background-color:#FFF}.message-footer input[type=text]{font-size:12px;width:34px;height:24px;line-height:20px;margin-bottom:0;padding:3px;vertical-align:middle;text-align:center}.message-footer-style2 .pagination>li>a,.message-footer-style2 .pagination>li>span{border:1px solid #B5B5B5;border-radius:100%!important;width:26px;height:26px;line-height:26px;display:inline-block;text-align:center;padding:0}.message-footer-style2 .pagination>li.disabled>span,.message-footer-style2 .pagination>li>span{border-color:#CCC}.message-footer-style2 .pagination>li>a:hover{border-color:#84AFC9;background-color:#F7F7F7}.message-item.message-inline-open{background-color:#F2F6F9;border:1px solid #DDD;border-bottom-color:#CCC}.message-item.message-inline-open:first-child{border-top-color:#EEE}.message-item.message-inline-open:last-child{border-bottom-color:#DDD}.message-item.message-inline-open+.message-item{border-bottom-color:transparent}.message-loading-overlay{position:absolute;z-index:14;top:0;bottom:0;right:0;left:0;background-color:rgba(255,255,255,.5);text-align:center}.message-loading-overlay>.ace-icon{position:absolute;top:15%;left:0;right:0;text-align:center}.message-content .sender{color:#6A9CBA;font-weight:700;width:auto;text-overflow:inherit;vertical-align:middle;margin:0}.message-content .time{width:auto;text-overflow:inherit;white-space:normal;float:none;vertical-align:middle}ul.attachment-list{margin:6px 0 4px 8px}ul.attachment-list>li{margin-bottom:3px}.message-attachment{padding-left:10px;padding-right:10px}.attached-file{color:#777;width:200px;display:inline-block}.attached-file>.ace-icon{display:inline-block;width:16px;margin-right:2px;vertical-align:middle}.attached-file:hover{text-decoration:none;color:#438EB9}.attached-file:hover .attached-name{color:#2283C5}.attached-file .attached-name{display:inline-block;max-width:175px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;vertical-align:middle}.messagebar-item-left,.messagebar-item-right{position:absolute;bottom:14px;left:12px;text-align:left}.messagebar-item-right{right:12px;left:auto}.message-navbar .nav-search{right:auto;left:5px;top:auto;bottom:11px}.message-navbar .messagebar-item-left~.nav-search{left:60px}.message-form{border:1px solid #ddd;border-top:none;padding-top:22px}@media only screen and (max-width:480px){.message-form{padding-left:16px;padding-right:16px}}.message-form .form-actions{margin-bottom:0}.message-form .wysiwyg-editor{overflow:auto;min-height:150px;max-height:250px;height:auto}.btn-send-message{position:relative;top:6px;vertical-align:middle}.btn-back-message-list{color:#777}.btn-back-message-list:hover{color:#478FCA;text-decoration:none}.message-condensed .message-item{padding-top:8px;padding-bottom:9px}.message-condensed .message-footer,.message-condensed .message-navbar{padding-top:7px;padding-bottom:7px}.message-condensed .messagebar-item-left,.message-condensed .messagebar-item-right{bottom:9px}.message-condensed .message-navbar .nav-search{bottom:7px}@media only screen and (max-width:480px){.message-condensed .message-bar{min-height:42px}}.inbox-folders .btn-block{margin-top:0}@media only screen and (max-width:767px){.inbox-folders.inbox-folders-responsive .btn-block{width:24%}}@media only screen and (max-width:600px){.inbox-folders.inbox-folders-responsive .btn-block{width:48%}}@media only screen and (max-width:320px){.inbox-folders.inbox-folders-responsive .btn-block{width:99%}}.inbox-folders .btn-lighter,.inbox-folders .btn-lighter.active{background-color:#F4F4F4!important;text-shadow:none!important;color:#7C8395!important;border:1px solid #FFF!important;padding:5px 11px}.inbox-folders .btn-lighter.active{background-color:#EDF2F8!important;color:#53617C!important}.inbox-folders .btn-lighter:hover{background-color:#EFEFEF!important;color:#6092C4!important}.inbox-folders .btn>.ace-icon:first-child{display:inline-block;width:14px;text-align:left}.inbox-folders .btn-lighter+.btn-lighter{border-top-width:0!important}.inbox-folders .btn.active:before{display:block;content:"";position:absolute;top:1px;bottom:1px;left:-1px;border-left:3px solid #4F99C6}.inbox-folders .btn.active:after{display:none}.inbox-folders .btn .counter{border-radius:3px;position:absolute;right:8px;top:8px;padding-left:6px;padding-right:6px;opacity:.75;filter:alpha(opacity=75)}.inbox-folders .btn:hover .badge{opacity:1;filter:alpha(opacity=100)}.timeline-container{position:relative;padding-top:4px;margin-bottom:32px}.timeline-container:last-child{margin-bottom:0}.timeline-container:before{content:"";display:block;position:absolute;left:28px;top:0;bottom:0;border:1px solid #E2E3E7;background-color:#E7EAEF;width:4px;border-width:0 1px}.timeline-container:first-child:before{border-top-width:1px}.timeline-container:last-child:before{border-bottom-width:1px}.timeline-item{position:relative;margin-bottom:8px}.timeline-item .widget-box{background-color:#F2F6F9;color:#595C66}.timeline-item .transparent.widget-box{border-left:3px solid #DAE1E5}.timeline-item .transparent .widget-header{background-color:#ECF1F4;border-bottom-width:0}.timeline-item .transparent .widget-header>.widget-title{margin-left:8px}.timeline-item:nth-child(even) .widget-box{background-color:#F3F3F3;color:#616161}.timeline-item:nth-child(even) .widget-box.transparent{border-left-color:#DBDBDB!important}.timeline-item:nth-child(even) .widget-box.transparent .widget-header{background-color:#EEE!important}.timeline-item .widget-box{margin:0 0 0 60px;position:relative;max-width:none}.timeline-item .widget-main{margin:0;position:relative;max-width:none;border-bottom-width:0}.timeline-item .widget-body{background-color:transparent}.timeline-item .widget-toolbox{padding:4px 8px 0!important;background-color:transparent!important;border-width:0!important;margin:0!important}.timeline-info{float:left;width:60px;text-align:center;position:relative}.timeline-info img{border-radius:100%;max-width:42px}.timeline-info .badge,.timeline-info .label{font-size:12px}.timeline-container:not(.timeline-style2) .timeline-indicator{opacity:1;border-radius:100%;display:inline-block;font-size:16px;height:36px;line-height:30px;width:36px;text-align:center;text-shadow:none!important;padding:0;cursor:default;border:3px solid #FFF!important}.timeline-label{display:block;clear:both;margin:0 0 18px 34px}.timeline-item img{border:1px solid #AAA;padding:2px;background-color:#FFF}.timeline-style2:before{display:none}.timeline-style2 .timeline-item{padding-bottom:22px;margin-bottom:0}.timeline-style2 .timeline-item:last-child{padding-bottom:0}.timeline-style2 .timeline-item:before{content:"";display:block;position:absolute;left:90px;top:5px;bottom:-5px;border-width:0;background-color:#DDD;width:2px;max-width:2px}.timeline-style2 .timeline-item:last-child:before{display:none}.timeline-style2 .timeline-item:first-child:before{display:block}.timeline-style2 .timeline-item .transparent .widget-header{background-color:transparent!important}.timeline-style2 .timeline-item .transparent.widget-box{background-color:transparent!important;border-left:none!important}.timeline-style2 .timeline-info{width:100px}.timeline-style2 .timeline-indicator{font-size:0;height:12px;line-height:12px;width:12px;border-width:1px!important;background-color:#FFF!important;position:absolute;left:85px;top:3px;opacity:1;border-radius:100%;display:inline-block;padding:0}.timeline-style2 .timeline-date{display:inline-block;width:72px;text-align:right;margin-right:25px;color:#777}.timeline-style2 .timeline-item .widget-box{margin-left:112px}.timeline-style2 .timeline-label{width:75px;margin-left:0;margin-bottom:10px;text-align:right;color:#666;font-size:14px}.timeline-time{text-align:center;position:static}.dataTables_length select{width:70px;height:25px;padding:2px 3px}.dataTables_length label{font-weight:400}.dataTables_filter{text-align:right}.dataTables_filter input[type=search],.dataTables_filter input[type=text]{width:125px;height:18px;line-height:18px;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;padding:4px 6px}.dataTables_filter label{font-weight:400}.dataTables_info{font-size:14px}.dataTables_paginate{text-align:right}.dataTables_paginate .pagination{margin:0 12px}.dataTables_wrapper label{display:inline-block;font-size:13px}.dataTables_wrapper input[type=search],.dataTables_wrapper input[type=text],.dataTables_wrapper select{margin-bottom:0!important;margin:0 4px}.dataTables_wrapper .row{margin:0!important}.dataTables_wrapper .row:first-child{padding-top:12px;padding-bottom:12px;background-color:#EFF3F8}.dataTables_wrapper .row:first-child+.dataTable{border-top:1px solid #ddd;border-bottom:1px solid #ddd}.dataTables_wrapper .row:last-child{border-bottom:1px solid #e0e0e0;padding-top:12px;padding-bottom:12px;background-color:#EFF3F8}.dataTables_wrapper .dataTables_scroll+.row{border-top:1px solid #e0e0e0}.dataTable{margin-bottom:0}.dataTable>thead>tr>th[class*=sort]{cursor:pointer}.dataTable>thead>tr>th[class*=sort]:after{float:right;display:inline;content:"\f0dc";font-family:FontAwesome;font-size:13px;font-weight:400;color:#555}.dataTable>thead>tr>th[class*=sort]:hover{color:#547ea8}.dataTable>thead>tr>th[class*=sorting_]{color:#307ecc}.dataTable>thead>tr>th.sorting_asc,.dataTable>thead>tr>th.sorting_desc{background-image:-webkit-linear-gradient(top,#eff3f8 0,#e3e7ed 100%);background-image:-o-linear-gradient(top,#eff3f8 0,#e3e7ed 100%);background-image:linear-gradient(to bottom,#eff3f8 0,#e3e7ed 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffeff3f8', endColorstr='#ffe3e7ed', GradientType=0)}.dataTable>thead>tr>th.sorting_desc:after{content:"\f0dd";top:-6px;color:#307ecc}.dataTable>thead>tr>th.sorting_asc:after{content:"\f0de";top:4px;color:#307ecc}.dataTable>thead>tr>th.sorting_disabled{cursor:inherit}.dataTable>thead>tr>th.sorting_disabled:after,.dataTables_scrollHead+.dataTables_scrollBody>.dataTable>thead>tr>th:after{display:none}.dataTables_scrollHeadInner{width:auto!important}.dataTables_scrollHeadInner>.dataTable>thead>tr>th{border-bottom-width:0!important}.dataTables_borderWrap .dataTables_scrollBody,.dataTables_borderWrap .dataTables_scrollHead{border:1px solid #ddd!important;border-width:0 1px!important}.dataTables_borderWrap .dataTables_scrollBody .table-bordered,.dataTables_borderWrap .dataTables_scrollHead .table-bordered{border-left-width:0;border-right-width:0}.dataTables_borderWrap .dataTables_scrollBody .table-bordered>tbody>tr>td:first-child,.dataTables_borderWrap .dataTables_scrollBody .table-bordered>thead>tr>th:first-child,.dataTables_borderWrap .dataTables_scrollHead .table-bordered>tbody>tr>td:first-child,.dataTables_borderWrap .dataTables_scrollHead .table-bordered>thead>tr>th:first-child{border-left-width:0}.dataTables_borderWrap .dataTables_scrollBody .table-bordered>tbody>tr>td:last-child,.dataTables_borderWrap .dataTables_scrollBody .table-bordered>thead>tr>th:last-child,.dataTables_borderWrap .dataTables_scrollHead .table-bordered>tbody>tr>td:last-child,.dataTables_borderWrap .dataTables_scrollHead .table-bordered>thead>tr>th:last-child{border-right-width:0}table.dataTable{clear:both;max-width:none!important}table.dataTable th:active{outline:0}div.dataTables_scrollHead table{margin-bottom:0!important;border-bottom-left-radius:0;border-bottom-right-radius:0}div.dataTables_scrollHead table thead tr:last-child td:first-child,div.dataTables_scrollHead table thead tr:last-child th:first-child{border-bottom-left-radius:0!important;border-bottom-right-radius:0!important}div.dataTables_scrollBody table{border-top:none;margin-top:0!important;margin-bottom:0!important}div.dataTables_scrollBody tbody tr:first-child td,div.dataTables_scrollBody tbody tr:first-child th{border-top:none}div.dataTables_scrollFoot table{margin-top:0!important;border-top:none}.DTTT_Print .main-content{margin-left:0!important;margin-right:0!important}.fc-header-title>h2{font-size:22px;color:#65A0CE}.fc-widget-content,.fc-widget-header{border:1px solid #BCD4E5}.fc-state-highlight{background:#FFC}.fc-event-skin{border:none!important;background-color:#ABBAC3;padding:0 0 1px 2px}.label-yellow .fc-event-skin{color:#963}.label-light .fc-event-skin{color:#888}[class*=label-]>.fc-event-skin,[class*=label-]>.fc-event-skin>.fc-event-skin.fc-event-head{background-color:inherit}.fc-event-skin.ui-draggable-dragging{cursor:move}.fc-event-skin.fc-event-vert,.fc-event-vert>.fc-event-skin{padding:0 0 1px}.fc-grid .fc-day-number{color:#2E6589}.fc-widget-header{background:#ECF2F7;color:#8090A0}.fc-event-hori,.fc-event-vert{border-radius:0!important;border-color:transparent}.fc-event-vert .fc-event-content{padding-left:1px;padding-right:1px}.fc-event-vert .fc-event-time{padding:0}.fc-state-default,.fc-state-default .fc-button-inner{border:none;background-color:#ABBAC3;color:#FFF;background-image:none;box-shadow:none;text-shadow:none;border-radius:0!important;margin-left:2px}.fc-state-default .fc-button-effect{display:none}.fc-state-disabled,.fc-state-disabled .fc-button-inner{opacity:.75;filter:alpha(opacity=75);color:#DDD}.fc-state-active,.fc-state-active .fc-button-inner{border-color:#4F99C6;background-color:#6FB3E0}.fc-state-hover,.fc-state-hover .fc-button-inner{background-color:#8B9AA3}.external-event{margin:6px 0;padding:0;cursor:default;display:block;color:#FFF;background-color:#ABBAC3;font-size:13px;line-height:28px}.external-event:hover{opacity:1;filter:alpha(opacity=100)}.external-event.ui-draggable-dragging{cursor:move}.external-event>.ace-icon:first-child{display:inline-block;height:32px;width:32px;text-align:center;line-height:30px;margin-right:5px;font-size:15px;border-right:1px solid #FFF}@media only screen and (max-width:480px){.fc-header td{display:block;width:auto;text-align:left}}.chosen-container+.help-inline{vertical-align:middle}.chosen-select{display:inline!important;visibility:hidden;opacity:0;position:absolute;z-index:-1;width:0;height:0;border-width:0}.chosen-container,[class*=chosen-container]{vertical-align:middle}.chosen-container>.chosen-single,[class*=chosen-container]>.chosen-single{line-height:28px;height:30px;box-shadow:none;background:#FAFAFA}.chosen-choices{box-shadow:none!important}.chosen-container-single .chosen-single abbr{background:0 0}.chosen-container-single .chosen-single abbr:after{content:"\f00d";display:inline-block;color:#888;font-family:FontAwesome;font-size:13px;position:absolute;right:0;top:-7px}.chosen-container-single .chosen-single abbr:hover:after,.chosen-container-single.chosen-disabled .chosen-single abbr:hover:after{color:#464646}.chosen-single div b{background:none!important}.chosen-single div b:before{content:"\f0d7";display:inline-block;color:#888;font-family:FontAwesome;font-size:12px;position:relative;top:-1px;left:1px}.chosen-container-active.chosen-with-drop .chosen-single div b:before{content:"\f0d8"}.chosen-container-single .chosen-search{position:relative}.chosen-container-single .chosen-search input[type=text]{background:0 0;border-radius:0;line-height:28px;height:28px}.chosen-container-single .chosen-search:after{content:"\f002";display:inline-block;color:#888;font-family:FontAwesome;font-size:14px;position:absolute;top:8px;right:12px}.chosen-container-multi .chosen-choices li.search-field input[type=text]{height:25px}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close{background:0 0}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:before{content:"\f00d";display:inline-block;color:#888;font-family:FontAwesome;font-size:13px;position:absolute;right:2px;top:-1px}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover{text-decoration:none}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover:before,.chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close:before{color:#464646}.chosen-container .chosen-results-scroll-down span,.chosen-container .chosen-results-scroll-up span{background:0 0}.chosen-container .chosen-results-scroll-down span:before,.chosen-container .chosen-results-scroll-up span:before{content:"\f0d7";display:inline-block;color:#888;font-family:FontAwesome;font-size:12px;position:relative;top:-1px;left:1px}.chosen-container .chosen-results-scroll-up span:before,.chosen-container-active .chosen-single-with-drop div b:before{content:"\f0d8"}.chosen-rtl .chosen-search input[type=text]{background:0 0}.chosen-rtl .chosen-search:after{content:"";display:none}.chosen-rtl .chosen-search:before{content:"\f002";display:inline-block;color:#888;font-family:FontAwesome;font-size:14px;position:absolute;top:9px;left:12px}.chosen-container-single .chosen-single{border-radius:0}.chosen-container .chosen-results li.highlighted{background:#316AC5;color:#FFF}.chosen-container-single .chosen-drop{border-radius:0;border-bottom:3px solid #4492C9;border-color:#4492C9}.chosen-container-active .chosen-single,.chosen-single.chosen-single-with-drop{border-color:#4492C9}.form-group.has-error .chosen-single{border-color:#f09784!important}.form-group.has-info .chosen-single{border-color:#64a6bc!important}.form-group.has-warning .chosen-single{border-color:#e0c43a!important}.form-group.has-success .chosen-single{border-color:#92bf65!important}.chosen-container-active.chosen-with-drop .chosen-single{border-color:#4492C9}.chosen-container .chosen-drop{display:none}.chosen-container.chosen-with-drop .chosen-drop{left:auto;right:auto;display:block}@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min-resolution:144dpi){.chosen-container .chosen-results-scroll-down span,.chosen-container .chosen-results-scroll-up span,.chosen-container-multi .chosen-choices li.search-choice .search-choice-close,.chosen-container-single .chosen-search input[type=text],.chosen-container-single .chosen-single abbr,.chosen-container-single .chosen-single div b,.chosen-rtl .chosen-search input[type=text]{background-image:none!important;background-repeat:no-repeat!important;background-size:auto!important}}.tag-input-style+.chosen-container-multi .chosen-choices li.search-choice{background-image:none;background-color:#91b8d0;color:#FFF;display:inline-block;font-size:13px;font-weight:400;margin-bottom:3px;margin-right:0;padding:6px 22px 7px 9px;position:relative;text-shadow:1px 1px 1px rgba(0,0,0,.15);transition:all .2s ease 0s;vertical-align:baseline;white-space:nowrap;border:none;-webkit-box-shadow:none;box-shadow:none;border-radius:0}.tag-input-style+.chosen-container-multi .chosen-choices li.search-choice .search-choice-close{position:absolute;top:0;bottom:0;right:0;width:18px;height:auto;line-height:25px;text-align:center}.tag-input-style+.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:before{color:#FFF;position:static;font-size:11px}.tag-input-style+.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover{background-color:rgba(0,0,0,.2)}.tag-input-style+.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover:before{color:#FFF}.tag-input-style+.chosen-container-multi.chosen-rtl .chosen-choices li.search-choice{padding:6px 9px 7px 22px;margin-left:0;margin-right:3px!important}.tag-input-style+.chosen-container-multi.chosen-rtl .chosen-choices li.search-choice .search-choice-close{right:auto;left:0}.select2-container .select2-choice{border-radius:0;height:30px}.select2-container.select2-drop-above .select2-choice{border-radius:0}.select2-container[class*=input-]{max-width:none}.select2-container.input-mini{min-width:100px}.select2-container .select2-choice abbr,.select2-search-choice-close{background:0 0}.select2-container .select2-choice abbr:before,.select2-search-choice-close:before{font-family:FontAwesome;font-size:12px;display:inline;content:"\f00d";color:#888;position:relative;top:-1px}.select2-container .select2-choice abbr:hover:before,.select2-search-choice-close:hover:before{color:#555}.select2-container .select2-choice abbr:before{top:-7px}.select2-search-choice-close:hover{text-decoration:none!important}.select2-drop{border-radius:0;border:1px solid #4492C9;border-width:0 1px 3px}.select2-drop.select2-drop-above{border-radius:0}.select2-container .select2-choice{background:#FAFAFA}.select2-container-active .select2-choice,.select2-container-active .select2-choices,.select2-container-multi.select2-container-active .select2-choices,.select2-dropdown-open.select2-drop-above .select2-choice,.select2-dropdown-open.select2-drop-above .select2-choices{border-color:#4492C9}.select2-results .select2-highlighted{background:#316AC5}.select2-container .select2-choice .select2-arrow{border-radius:0;background:0 0;border:none}.select2-container .select2-choice .select2-arrow b{background:0 0}.select2-container .select2-choice .select2-arrow b:before{font-family:FontAwesome;font-size:12px;display:inline;content:"\f0d7";color:#888;position:relative;left:5px}.select2-dropdown-open .select2-choice .select2-arrow b:before{content:"\f0d8"}.select2-search .select2-input{background:#fff;margin-top:4px}.select2-search:after{font-family:FontAwesome;font-size:14px;display:inline;content:"\f002";color:#777;position:relative;top:0;left:-20px;z-index:0}.select2-container-multi .select2-choices .select2-search-field input{border:none!important;-webkit-box-shadow:none!important;box-shadow:none!important;background:none!important}.select2-container-active .select2-choice,.select2-container-active .select2-choices,.select2-container-multi.select2-container-active .select2-choices,.select2-dropdown-open.select2-drop-above .select2-choice,.select2-dropdown-open.select2-drop-above .select2-choices{-webkit-box-shadow:none;box-shadow:none}.select2-search input.select2-active{background-color:#FFF;position:relative;z-index:1}@media only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min-resolution:144dpi){.select2-container .select2-choice abbr,.select2-container .select2-choice div b,.select2-search input,.select2-search-choice-close{background-image:none!important;background-size:auto!important}.select2-search input{background-position:auto!important}}.select2-container-active.select2-dropdown-open .select2-choice{background-image:-webkit-linear-gradient(top,#eee 0,#fff 100%);background-image:-o-linear-gradient(top,#eee 0,#fff 100%);background-image:linear-gradient(to bottom,#eee 0,#fff 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffeeeeee', endColorstr='#ffffffff', GradientType=0)}.select2-container-active.select2-drop-above .select2-choice{background-image:-webkit-linear-gradient(top,#fff 0,#eee 100%);background-image:-o-linear-gradient(top,#fff 0,#eee 100%);background-image:linear-gradient(to bottom,#fff 0,#eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffeeeeee', GradientType=0)}.form-group.has-error .select2-choice,.form-group.has-error .select2-choices{border-color:#f09784!important}.form-group.has-info .select2-choice,.form-group.has-info .select2-choices{border-color:#64a6bc!important}.form-group.has-warning .select2-choice,.form-group.has-warning .select2-choices{border-color:#e0c43a!important}.form-group.has-success .select2-choice,.form-group.has-success .select2-choices{border-color:#92bf65!important}@media only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min-resolution:144dpi){.select2-container .select2-choice .select2-arrow b,.select2-container .select2-choice abbr,.select2-search input,.select2-search-choice-close{background-image:none!important;background-repeat:no-repeat!important;background-size:auto!important}.select2-search input{background-position:auto!important}}#colorbox:active,#colorbox:focus{outline:0}#cboxBottomCenter,#cboxBottomLeft,#cboxBottomRight,#cboxMiddleLeft,#cboxMiddleRight,#cboxTopCenter,#cboxTopLeft,#cboxTopRight{background:none!important;opacity:0}#cboxContent{border:12px solid #000;background-color:#FFF;padding:7px}#cboxOverlay{background:#000}#cboxCurrent{left:64px;margin-bottom:4px;font-size:14px}#cboxTitle{margin-bottom:4px;font-size:14px;color:#777}#cboxClose,#cboxNext,#cboxPrevious{background:0 0;text-indent:0;width:26px;height:26px;line-height:22px;padding:0 4px;text-align:center;border:2px solid #999;border-radius:16px;color:#666;font-size:12px;margin-left:5px;margin-bottom:5px}#cboxNext:hover,#cboxPrevious:hover{color:#333;border-color:#666}#cboxContent{overflow:visible}#cboxClose{background-color:#000;border:2px solid #FFF;border-radius:32px;color:#FFF;font-size:21px;height:28px;width:28px;padding-bottom:2px;margin-left:0;right:-14px;top:-14px}#cboxLoadingOverlay{background:none!important}#cboxLoadingGraphic{background:#FFF!important;text-align:center}#cboxLoadingGraphic>.ace-icon{display:inline-block;background-color:#FFF;border-radius:8px;width:32px;height:32px;position:relative;top:48%;text-align:center;vertical-align:middle;-moz-animation:spin 1.5s infinite linear;-webkit-animation:spin 1.5s infinite linear;-o-animation:spin 1.5s infinite linear;-ms-animation:spin 1.5s infinite linear;animation:spin 1.5s infinite linear;font-size:24px;color:#FE7E3E}.ace-spinner{display:inline-block}.ace-spinner .spinner-buttons{min-width:18px}.ace-spinner .spinner-buttons>.btn{border-radius:0!important;font-size:10px;padding:0;width:18px;height:14px;line-height:8px;margin-left:0}.ace-spinner .spinner-buttons>.btn:first-child{margin-top:0}.ace-spinner .spinner-buttons>.btn>.ace-icon{margin:0;padding:0}.ace-spinner .spinner-buttons>button.btn.spinner-up:active{top:-1px}.ace-spinner .spinner-input{text-align:center;height:29px;line-height:1.2;color:#777}.ace-spinner.touch-spinner .spinner-buttons{margin:0;font-size:0}.ace-spinner.touch-spinner .spinner-buttons>.btn{height:29px;line-height:16px;width:24px;font-size:18px;display:inline-block;vertical-align:sub;margin:0 1px!important}.ace-spinner.touch-spinner .spinner-buttons>.btn>.ace-icon{vertical-align:middle;display:inline-block}.wizard-steps{list-style:none;display:table;width:100%;padding:0;margin:0;position:relative}.wizard-steps li{display:table-cell;text-align:center;width:1%}.wizard-steps li .step{border:5px solid #ced1d6;color:#546474;font-size:15px;border-radius:100%;background-color:#FFF;position:relative;z-index:2;display:inline-block;width:40px;height:40px;line-height:30px;text-align:center}.wizard-steps li:before{display:block;content:"";width:100%;height:1px;font-size:0;overflow:hidden;border-top:4px solid #CED1D6;position:relative;top:21px;z-index:1}.wizard-steps li:last-child:before{max-width:50%;width:50%}.wizard-steps li:first-child:before{max-width:51%;left:50%}.wizard-steps li.active .step,.wizard-steps li.active:before,.wizard-steps li.complete .step,.wizard-steps li.complete:before{border-color:#5293c4}.wizard-steps li.complete .step{cursor:default;color:#FFF;-webkit-transition:transform ease .1s;-o-transition:transform ease .1s;transition:transform ease .1s}.wizard-steps li.complete .step:before{display:block;position:absolute;top:0;left:0;bottom:0;right:0;line-height:30px;text-align:center;border-radius:100%;content:"\f00c";background-color:#FFF;z-index:3;font-family:FontAwesome;font-size:17px;color:#87ba21}.wizard-steps li.complete:hover .step{-moz-transform:scale(1.1);-webkit-transform:scale(1.1);-o-transform:scale(1.1);-ms-transform:scale(1.1);transform:scale(1.1);border-color:#80afd4}.wizard-steps li.complete:hover:before{border-color:#80afd4}.wizard-steps li .title{display:block;margin-top:4px;max-width:100%;color:#949ea7;font-size:14px;z-index:104;text-align:center;table-layout:fixed;word-wrap:break-word}.wizard-steps li.active .title,.wizard-steps li.complete .title{color:#2b3d53}.step-content{position:relative}.step-content .step-pane{display:none;min-height:200px;padding:4px 8px 12px}.step-content .step-pane.active{display:block}.wizard-actions{text-align:right}@media only screen and (max-width:767px){.wizard-steps li .step{width:30px;height:30px;line-height:24px;border-width:3px}.wizard-steps li:after,.wizard-steps li:before{border-width:3px}.wizard-steps li.complete .step:before{line-height:24px;font-size:13px}.wizard-steps li:before{top:16px}.step-content .step-pane{padding:4px 4px 6px;min-height:150px}}.tree{padding-left:9px;overflow-x:hidden;overflow-y:auto;position:relative}.tree:before{display:inline-block;content:"";position:absolute;top:-20px;bottom:16px;left:0;z-index:1;border:1px dotted #67b2dd;border-width:0 0 0 1px}.tree .tree-folder{width:auto;min-height:20px;cursor:pointer}.tree .tree-folder .tree-folder-header{position:relative;height:20px;line-height:20px}.tree .tree-folder .tree-folder-header:hover{background-color:#F0F7FC}.tree .tree-folder .tree-folder-header .tree-folder-name,.tree .tree-item .tree-item-name{display:inline;z-index:2}.tree .tree-folder .tree-folder-header>.ace-icon:first-child,.tree .tree-item>.ace-icon:first-child{display:inline-block;position:relative;z-index:2;top:-1px}.tree .tree-folder .tree-folder-header .tree-folder-name{margin-left:2px}.tree .tree-folder .tree-folder-header>.ace-icon:first-child{margin:-2px 0 0 -2px}.tree .tree-folder:last-child:after{display:inline-block;content:"";position:absolute;z-index:1;top:15px;bottom:0;left:-15px;border-left:1px solid #FFF}.tree .tree-folder .tree-folder-content{margin-left:23px;position:relative}.tree .tree-folder .tree-folder-content:before{display:inline-block;content:"";position:absolute;z-index:1;top:-14px;bottom:16px;left:-14px;border:1px dotted #67b2dd;border-width:0 0 0 1px}.tree .tree-item{height:20px;line-height:20px;cursor:pointer}.tree .tree-item:hover{background-color:#F0F7FC}.tree .tree-item .tree-item-name{margin-left:3px}.tree .tree-item .tree-item-name>.ace-icon:first-child{margin-right:3px}.tree .tree-item>.ace-icon:first-child{margin-top:-1px}.tree .tree-folder,.tree .tree-item{position:relative}.tree .tree-folder:before,.tree .tree-item:before{display:inline-block;content:"";position:absolute;top:14px;left:-13px;width:18px;height:0;border-top:1px dotted #67b2dd;z-index:1}.tree .tree-selected{background-color:rgba(98,168,209,.1);color:#6398B0}.tree .tree-selected:hover{background-color:rgba(98,168,209,.1)}.tree .tree-folder,.tree .tree-item{border:1px solid #FFF}.tree .tree-folder .tree-folder-header{border-radius:0}.tree .tree-folder .tree-folder-header,.tree .tree-item{margin:0;padding:5px;color:#4D6878;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.tree .tree-item>.ace-icon:first-child{color:#F9E8CE;width:13px;height:13px;line-height:13px;font-size:11px;text-align:center;border-radius:3px;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;background-color:#FAFAFA;border:1px solid #CCC;box-shadow:0 1px 2px rgba(0,0,0,.05)}.tree .tree-selected>.ace-icon:first-child{background-color:#F9A021;border-color:#F9A021;color:#FFF}.tree .tree-minus.ace-icon:first-child,.tree .tree-plus.ace-icon:first-child{font-style:normal;vertical-align:middle;height:11px;width:11px;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;text-align:center;border:1px solid #8BAEBF;line-height:10px;background-color:#FFF;position:relative;z-index:1}.tree .tree-minus.ace-icon:first-child:before,.tree .tree-plus.ace-icon:first-child:before{content:"";display:block;width:7px;height:0;border-top:1px solid #4D6878;position:absolute;top:5px;left:2px}.tree .tree-plus.ace-icon:first-child:after{content:"";display:block;height:7px;width:0;border-left:1px solid #4D6878;position:absolute;top:2px;left:5px}.tree .tree-unselectable .tree-item>.ace-icon:first-child{color:#5084A0;width:13px;height:13px;line-height:13px;font-size:10px;text-align:center;border-radius:0;background-color:transparent;border:none;box-shadow:none}.tree .ace-icon[class*="-down"]{transform:rotate(-45deg)}.tree .fa-spin{height:auto}.tree .tree-loading{margin-left:36px}.tree img{display:inline;veritcal-align:middle}.gritter-item-wrapper{background-image:none!important;box-shadow:0 2px 10px rgba(50,50,50,.5);background:rgba(50,50,50,.92)}.gritter-item-wrapper.gritter-info{background:rgba(49,81,133,.92)}.gritter-item-wrapper.gritter-error{background:rgba(153,40,18,.92)}.gritter-item-wrapper.gritter-success{background:rgba(89,131,75,.92)}.gritter-item-wrapper.gritter-warning{background:rgba(190,112,31,.92)}.gritter-item-wrapper.gritter-light{background:rgba(245,245,245,.95);border:1px solid #BBB}.gritter-item-wrapper.gritter-light.gritter-info{background:rgba(232,242,255,.95)}.gritter-item-wrapper.gritter-light.gritter-info .gritter-item{color:#4A577D}.gritter-item-wrapper.gritter-light.gritter-error{background:rgba(255,235,235,.95)}.gritter-item-wrapper.gritter-light.gritter-error .gritter-item{color:#894A38}.gritter-item-wrapper.gritter-light.gritter-success{background:rgba(239,250,227,.95)}.gritter-item-wrapper.gritter-light.gritter-success .gritter-item{color:#416131}.gritter-item-wrapper.gritter-light.gritter-warning{background:rgba(252,248,227,.95)}.gritter-item-wrapper.gritter-light.gritter-warning .gritter-item{color:#946446}.gritter-item p{line-height:1.8}.gritter-bottom,.gritter-item,.gritter-top{background-image:none}.gritter-close{left:auto;right:3px;background-image:none;width:18px;height:18px;line-height:17px;text-align:center;border:2px solid transparent;border-radius:16px;color:#E17B67}.gritter-close:before{font-family:FontAwesome;font-size:16px;content:"\f00d"}.gritter-info .gritter-close{color:orange}.gritter-error .gritter-close,.gritter-success .gritter-close,.gritter-warning .gritter-close{color:#FFEA07}.gritter-close:hover{color:#FFF!important}.gritter-title{text-shadow:none}.gritter-light .gritter-bottom,.gritter-light .gritter-close,.gritter-light .gritter-item,.gritter-light .gritter-top{background-image:none;color:#444}.gritter-light .gritter-title{text-shadow:none}.gritter-light .gritter-close:hover{color:#8A3104!important}.gritter-center{position:fixed;left:33%;right:33%;top:33%}@media only screen and (max-width:767px){.gritter-center{left:16%;right:16%;top:30%}}@media only screen and (max-width:480px){.gritter-center{left:30px;right:30px}}@media only screen and (max-width:320px){.gritter-center{left:10px;right:10px}}.wysiwyg-editor{max-height:250px;height:250px;background-color:#F7F8FA;border-collapse:separate;border:1px solid #BBC0CA;padding:4px;box-sizing:content-box;overflow-y:scroll;overflow-x:hidden;outline:0}.wysiwyg-editor:focus{background-color:#FFF}.wysiwyg-toolbar{line-height:33px;margin:0!important;position:relative}.wysiwyg-toolbar .dropdown-menu{text-align:left}.wysiwyg-toolbar .btn-group{float:none!important;font-size:0}.wysiwyg-toolbar .btn-group>.btn{float:none;padding-left:0;padding-right:0;text-align:center;margin-left:1px}.wysiwyg-toolbar .btn-group>.btn>.ace-icon:first-child{font-size:14px;width:25px;max-width:25px;display:inline-block;border-width:1px!important}.wysiwyg-toolbar .btn-group>.btn.dropdown-toggle>.ace-icon:last-child{margin-right:4px}.wysiwyg-style1 .btn-group>.btn,.wysiwyg-style1 .btn-group>.inline>.btn,.wysiwyg-style2 .btn-group>.btn,.wysiwyg-style2 .btn-group>.inline>.btn{margin:0!important;background:#FFF!important;border-width:0!important;color:#ADB3BE!important;text-shadow:none!important}.wysiwyg-style1 .btn-group>.btn.active,.wysiwyg-style1 .btn-group>.inline>.btn.active,.wysiwyg-style2 .btn-group>.btn.active,.wysiwyg-style2 .btn-group>.inline>.btn.active{color:#5B80CE!important}.wysiwyg-style1 .btn-group>.btn.active:after,.wysiwyg-style1 .btn-group>.inline>.btn.active:after,.wysiwyg-style2 .btn-group>.btn.active:after,.wysiwyg-style2 .btn-group>.inline>.btn.active:after{display:none}.wysiwyg-style1 .btn-group,.wysiwyg-style2 .btn-group{position:relative}.wysiwyg-style1 .btn-group:after,.wysiwyg-style2 .btn-group:after{display:block;content:"";position:absolute;left:-2px;top:6px;bottom:6px;width:0;max-width:0;border-left:1px solid #E1E6EA}.wysiwyg-style1 .btn-group:first-child:after,.wysiwyg-style2 .btn-group:first-child:after{display:none}.wysiwyg-style2{background-color:#E5E5E5}.wysiwyg-style2+.wysiwyg-editor{border-color:#DDD;background-color:#FFF;border-top:none}.wysiwyg-style2 .btn-group>.btn,.wysiwyg-style2 .btn-group>.inline>.btn{margin:0 1px 0 0!important;background:#FFF!important;border:none!important;color:#8D939E!important;text-shadow:none!important}.wysiwyg-style2 .btn-group>.btn.active,.wysiwyg-style2 .btn-group>.inline>.btn.active{color:#FFF!important;background:#6AAEDF!important}.wysiwyg-style2 .btn-group:after{display:none}.wysiwyg-toolbar .btn-colorpicker{width:24px;height:24px;position:relative;background:#87B87F;background:-moz-linear-gradient(top,#cf3e73 10%,#fff 20%,#2283c5 30%,#fff 40%,#87b87f 50%,#fff 60%,#ffb752 70%,#fff 80%,#d15b47 90%,#fff 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(10%,#cf3e73),color-stop(20%,#fff),color-stop(30%,#2283c5),color-stop(40%,#fff),color-stop(50%,#87b87f),color-stop(60%,#fff),color-stop(70%,#ffb752),color-stop(80%,#fff),color-stop(90%,#d15b47),color-stop(100%,#fff));background:-webkit-linear-gradient(top,#cf3e73 10%,#fff 20%,#2283c5 30%,#fff 40%,#87b87f 50%,#fff 60%,#ffb752 70%,#fff 80%,#d15b47 90%,#fff 100%);background:-o-linear-gradient(top,#cf3e73 10%,#fff 20%,#2283c5 30%,#fff 40%,#87b87f 50%,#fff 60%,#ffb752 70%,#fff 80%,#d15b47 90%,#fff 100%);background:-ms-linear-gradient(top,#cf3e73 10%,#fff 20%,#2283c5 30%,#fff 40%,#87b87f 50%,#fff 60%,#ffb752 70%,#fff 80%,#d15b47 90%,#fff 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#CF3E73', endColorstr='#FFB752', GradientType=0);background:linear-gradient(top,#cf3e73 10%,#fff 20%,#2283c5 30%,#fff 40%,#87b87f 50%,#fff 60%,#ffb752 70%,#fff 80%,#d15b47 90%,#fff 100%)}.wysiwyg-toolbar .dropdown-colorpicker>.dropdown-menu{top:auto}.wysiwyg-toolbar input[type=file]{position:fixed;z-index:-10;opacity:0;max-width:0;max-height:0;display:block}.wysiwyg-toolbar .wysiwyg-choose-file{display:inline-block;width:auto;margin:4px auto 0;padding-left:5px;padding-right:5px}.wysiwyg-toolbar .dropdown-menu input[type=text]{margin-left:8px;margin-bottom:0}.wysiwyg-toolbar .dropdown-menu input[type=text].form-control{min-width:150px}.wysiwyg-toolbar .dropdown-menu .btn{margin-right:8px;margin-left:8px}.wysiwyg-style1 .btn-colorpicker{width:20px;height:20px;margin-left:4px}@media screen and (-webkit-min-device-pixel-ratio:0){.wysiwyg-editor img{display:inline!important}.wysiwyg-editor .ui-wrapper{border:1px dotted #D00;overflow:visible!important;display:inline-block!important;vertical-align:middle}.wysiwyg-editor .ui-wrapper:after{content:"";display:block;position:absolute;right:-3px;bottom:-3px;width:7px;height:7px;border:1px solid #D00;background-color:#FFF;z-index:1}}.widget-header .wysiwyg-toolbar{background-color:transparent}.widget-header .wysiwyg-toolbar .btn-group>.btn,.widget-header .wysiwyg-toolbar .btn-group>.inline>.btn{border-color:transparent;background:rgba(255,255,255,.25)!important;color:#FFF!important;min-width:32px;border-width:1px!important;border-radius:4px!important;padding:2px 1px 4px}.widget-header .wysiwyg-toolbar .btn-group>.btn.active,.widget-header .wysiwyg-toolbar .btn-group>.inline>.btn.active{background:rgba(0,0,0,.25)!important}.widget-body .wysiwyg-editor{border-width:0}.wysiwyg-speech-input{width:20px!important;color:transparent!important;background:0 0!important;border-width:0!important;-moz-transform:scale(2,2);-webkit-transform:scale(2,2);-o-transform:scale(2,2);-ms-transform:scale(2,2);transform:scale(2,2);-webkit-box-shadow:none!important;box-shadow:none!important;position:absolute;right:0;top:-10px;cursor:pointer}.wysiwyg-speech-input:focus{-webkit-box-shadow:none!important;box-shadow:none!important}.widget-body .md-header{margin-top:-30px;margin-left:9px}.widget-body .md-header .btn{border-color:transparent;background:rgba(255,255,255,.25)!important;color:#FFF!important;text-align:center;min-width:32px;border-width:1px!important;border-radius:4px!important;padding:2px 4px 4px}.widget-body .md-header .btn>.ace-icon{font-size:14px;width:25px;max-width:25px;display:inline-block}.widget-body .md-header .btn-inverse{background:rgba(0,0,0,.25)!important;padding-right:5px;margin-left:4px}.widget-body .md-preview{padding:8px;min-height:200px}.widget-body .md-input{border:none!important;box-shadow:none!important;display:block;margin-bottom:0;background-color:rgba(48,126,204,.07);padding:8px;width:100%}.widget-body .md-input:focus{background-color:#FFF;box-shadow:none!important}.editable-container .popover-title{color:#438EB9}.editable-click{border-bottom:1px dashed #BBB;cursor:pointer;font-weight:400}img.editable-click{border:1px dotted #BBB}.editable-click:hover{border-color:#08C;color:#08C}img.editable-click:hover{opacity:.75;filter:alpha(opacity=75)}.editable-buttons,.editable-input{display:inline-block}.editable-buttons{margin-left:1px}.editable-buttons .btn{padding:0;width:28px;line-height:24px;border-width:3px;font-size:12px;margin:0 1px 0 0}.editable-buttons .btn>.ace-icon{margin:0}.editable-clear-x{cursor:pointer;color:#888;background:0 0}.editable-clear-x:hover{color:#D15B47}.editable-clear-x:before{display:inline-block;content:"\f057";font-family:FontAwesome;font-size:15px;position:absolute;margin-top:-9px;width:16px;height:30px;line-height:30px;text-align:center}.editable-input .ace-spinner{margin-right:8px}.editable-input .ace-spinner .spinner-input{width:100%}.editable-inline .editable-slider{margin-top:10px;margin-right:4px}.editable-popup .editable-slider{display:block;margin-bottom:16px;margin-top:4px}.editable-slider input[type=text]{display:none}.editable-slider input[type=range]{outline:0!important}.editable-input .ace-file-input{display:block}.editable-image .ace-file-multiple .ace-file-container.selected{border-color:transparent}.editable-image+.editable-buttons,.editable-wysiwyg+.editable-buttons{display:block;text-align:center;margin-top:8px}.editable-wysiwyg{width:95%}.editable-wysiwyg .wysiwyg-editor{height:auto;overflow-y:hidden}.editableform .input-append.dropdown-menu{display:none}.editableform .open .input-append.dropdown-menu{display:block}.editable-container .editableform{margin-bottom:10px}.editable-inline .editableform{margin-bottom:0}.editableform .control-group{display:block}.editableform-loading{background:0 0}.editableform-loading .ace-icon,.editableform-loading .progress{position:relative;top:35%}.input-group.date .input-group-addon{cursor:pointer}.datepicker td,.datepicker th,.daterangepicker td,.daterangepicker th{border-radius:0!important;font-size:13px}.datepicker td.active,.datepicker td.active:hover,.daterangepicker td.active,.daterangepicker td.active:hover{background:#2283c5!important}.datepicker td.active.disabled,.datepicker td.active.disabled:hover,.daterangepicker td.active.disabled,.daterangepicker td.active.disabled:hover{background:#8b9aa3!important}.datepicker td,.datepicker th{min-width:32px}.datepicker-dropdown.datepicker-orient-bottom:after,.datepicker-dropdown.datepicker-orient-bottom:before{top:auto}.daterangepicker .calendar-date{border-radius:0}.datepicker-months .month,.datepicker-years .year{border-radius:0!important}.datepicker-months .month.active,.datepicker-months .month.active:active,.datepicker-months .month.active:focus,.datepicker-months .month.active:hover,.datepicker-years .year.active,.datepicker-years .year.active:active,.datepicker-years .year.active:focus,.datepicker-years .year.active:hover{background-image:none!important;background-color:#2283c5!important}.bootstrap-timepicker-widget table td input{width:32px}.well .datepicker table tr td.day:hover{background-color:#7d8893;color:#FFF}.bootstrap-timepicker-widget table td a:hover{border-radius:0}.daterangepicker.opensleft:before,.daterangepicker.opensright:before{-moz-border-bottom-colors:rgba(0,0,0,.2)}.daterangepicker.opensleft:after,.daterangepicker.opensright:after{-moz-border-bottom-colors:#fff}.datepicker-dropdown:before{-moz-border-bottom-colors:rgba(0,0,0,.2)}.datepicker-dropdown:after{-moz-border-bottom-colors:#fff}.datepicker-dropdown.datepicker-orient-bottom:before{-moz-border-top-colors:#999}.datepicker-dropdown.datepicker-orient-bottom:after{-moz-border-top-colors:#FFF}.bootstrap-timepicker-widget.dropdown-menu:before{-moz-border-bottom-colors:rgba(0,0,0,.2)}.bootstrap-timepicker-widget.dropdown-menu:after{-moz-border-bottom-colors:#FFF}.bootstrap-timepicker-widget.timepicker-orient-bottom:before{-moz-border-top-colors:#999}.bootstrap-timepicker-widget.timepicker-orient-bottom:after{-moz-border-top-colors:#FFF}.bootstrap-datetimepicker-widget [class=btn]{border-width:0!important;background-color:transparent!important;color:#777!important;text-shadow:none!important}.bootstrap-datetimepicker-widget [class=btn]:hover{color:#1B6AAA!important}.bootstrap-datetimepicker-widget .btn.btn-primary{border-width:3px!important}.bootstrap-datetimepicker-widget .picker-switch{margin-bottom:2px}.bootstrap-datetimepicker-widget .picker-switch .btn{width:90%!important;background-color:#EEE!important;color:#478fca!important;font-size:16px}.bootstrap-datetimepicker-widget .picker-switch .btn:hover{background-color:#e3edf5!important}.bootstrap-datetimepicker-widget td span{border-radius:0}.bootstrap-datetimepicker-widget .timepicker-hour,.bootstrap-datetimepicker-widget .timepicker-minute,.bootstrap-datetimepicker-widget .timepicker-second{color:#555!important}.ui-slider{background-color:#CCC}.ui-slider-horizontal{height:9px}.ui-slider-vertical{width:9px}.ui-slider .ui-slider-handle{border-radius:0;width:1.45em;height:1.45em;background-color:#F8F8F8;border:1px solid}.ui-slider .ui-slider-handle:after,.ui-slider .ui-slider-handle:before{display:block;content:"";position:absolute;top:4px;left:5px;width:4px;height:8px;border:1px solid;border-width:0 1px;border-color:inherit}.ui-slider .ui-slider-handle:after{left:8px;border-width:0 1px 0 0}.ui-slider .ui-slider-handle:hover{background-color:#FFF}.ui-slider .ui-slider-handle:active,.ui-slider .ui-slider-handle:focus,.ui-slider .ui-slider-handle:hover{outline:0;-webkit-box-shadow:1px 1px 1px 0 rgba(0,0,0,.3);box-shadow:1px 1px 1px 0 rgba(0,0,0,.3)}.ui-slider-horizontal .ui-slider-handle{margin-left:-.725em;top:-.4em}.ui-slider-vertical .ui-slider-handle{left:-.35em;margin-bottom:-.65em}.ui-slider-small.ui-slider-horizontal{height:5px}.ui-slider-small.ui-slider-vertical{width:5px}.ui-slider-small .ui-slider-handle{border-radius:100%;width:17px;height:17px;margin-bottom:-.45em;left:-.35em}.ui-slider-small .ui-slider-handle:after,.ui-slider-small .ui-slider-handle:before{height:7px;left:5px;width:3px}.ui-slider-small .ui-slider-handle:after{left:7px}.ui-slider-simple .ui-slider-handle:after,.ui-slider-simple .ui-slider-handle:before{display:none}.ui-slider-range{background-color:#4aa4ce}.ui-slider-handle{outline:0!important;border-color:#4aa4ce!important}.ui-state-disabled .ui-slider-range{background-color:#8daebe}.ui-state-disabled .ui-slider-handle{-webkit-box-shadow:none!important;box-shadow:none!important;border-color:#8daebe!important}.ui-slider-green .ui-slider-range{background-color:#8bbc67}.ui-slider-green .ui-slider-handle{border-color:#8bbc67!important}.ui-slider-green.ui-state-disabled .ui-slider-range{background-color:#aab2a4}.ui-slider-green.ui-state-disabled .ui-slider-handle{border-color:#aab2a4!important}.ui-slider-red .ui-slider-range{background-color:#d36e6e}.ui-slider-red .ui-slider-handle{border-color:#d36e6e!important}.ui-slider-red.ui-state-disabled .ui-slider-range{background-color:#caaaaa}.ui-slider-red.ui-state-disabled .ui-slider-handle{border-color:#caaaaa!important}.ui-slider-purple .ui-slider-range{background-color:#ac68ba}.ui-slider-purple .ui-slider-handle{border-color:#ac68ba!important}.ui-slider-purple.ui-state-disabled .ui-slider-range{background-color:#afa4b1}.ui-slider-purple.ui-state-disabled .ui-slider-handle{border-color:#afa4b1!important}.ui-slider-orange .ui-slider-range{background-color:#efad62}.ui-slider-orange .ui-slider-handle{border-color:#efad62!important}.ui-slider-orange.ui-state-disabled .ui-slider-range{background-color:#e1c4a3}.ui-slider-orange.ui-state-disabled .ui-slider-handle{border-color:#e1c4a3!important}.ui-slider-dark .ui-slider-range{background-color:#606060}.ui-slider-dark .ui-slider-handle{border-color:#606060!important}.ui-slider-dark.ui-state-disabled .ui-slider-range{background-color:#7a7a7a}.ui-slider-dark.ui-state-disabled .ui-slider-handle{border-color:#7a7a7a!important}.ui-slider-pink .ui-slider-range{background-color:#d6487e}.ui-slider-pink .ui-slider-handle{border-color:#d6487e!important}.ui-slider-pink.ui-state-disabled .ui-slider-range{background-color:#c58ca2}.ui-slider-pink.ui-state-disabled .ui-slider-handle{border-color:#c58ca2!important}.ui-datepicker{background-color:#FFF;border:1px solid rgba(0,0,0,.2);-webkit-box-shadow:0 2px 4px rgba(0,0,0,.2);box-shadow:0 2px 4px rgba(0,0,0,.2)}.ui-datepicker .ui-datepicker-next,.ui-datepicker .ui-datepicker-prev{height:26px;min-width:32px;max-width:32px;text-align:center;cursor:pointer;color:transparent;line-height:26px;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.ui-datepicker .ui-datepicker-next .ui-icon,.ui-datepicker .ui-datepicker-prev .ui-icon{color:transparent;visibility:hidden}.ui-datepicker .ui-datepicker-next:hover,.ui-datepicker .ui-datepicker-prev:hover{background-color:#EEE;text-decoration:none}.ui-datepicker .ui-datepicker-next:before,.ui-datepicker .ui-datepicker-prev:before{display:inline;font-family:FontAwesome;font-size:14px;content:"\f060";color:#393939}.ui-datepicker .ui-datepicker-next-hover,.ui-datepicker .ui-datepicker-prev-hover{top:2px}.ui-datepicker .ui-datepicker-next:before{content:"\f061"}.ui-datepicker .ui-datepicker-prev-hover{left:2px}.ui-datepicker .ui-datepicker-next-hover{right:2px}.ui-datepicker td{padding:0}.ui-datepicker td>a,.ui-datepicker td>span{display:inline-block;height:22px;min-width:24px;max-width:24px;text-align:center;color:#393939;font-size:13px;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.ui-datepicker td>a:hover{background-color:#EEE}.ui-datepicker td>a.ui-state-highlight{background-color:#D5E5EF}.ui-datepicker td>a.ui-state-active{background-color:#2283c5;color:#FFF}.ui-datepicker td>a.ui-priority-secondary{color:#888}.ui-datepicker td>span{color:#999}.ui-datepicker td .ui-datepicker-title select{height:24px;line-height:24px;padding:2px 3px}.ui-datepicker td .ui-datepicker-buttonpane{background-color:#DDD;height:1px}.ui-widget-overlay{background:rgba(0,0,0,.25);opacity:1!important;filter:alpha(opacity=100)!important;z-index:1040!important}.ui-dialog,.ui-jqdialog{z-index:1050!important;background-color:#FFF;padding:0;border:1px solid #DDD;-webkit-box-shadow:0 2px 4px rgba(0,0,0,.2);box-shadow:0 2px 4px rgba(0,0,0,.2)}.ui-dialog .ui-dialog-titlebar,.ui-dialog .ui-jqdialog-titlebar,.ui-jqdialog .ui-dialog-titlebar,.ui-jqdialog .ui-jqdialog-titlebar{background-color:#F1F1F1;font-size:16px;color:#669fc7;padding:0}.ui-dialog .ui-dialog-title,.ui-dialog .ui-jqdialog-title,.ui-jqdialog .ui-dialog-title,.ui-jqdialog .ui-jqdialog-title{float:none!important;width:auto}.ui-dialog .widget-header,.ui-jqdialog .widget-header{margin:0;border-width:0 0 1px}.ui-dialog .ui-dialog-buttonpane,.ui-dialog .ui-jqdialog-buttonpane,.ui-jqdialog .ui-dialog-buttonpane,.ui-jqdialog .ui-jqdialog-buttonpane{background-color:#eff3f8;border-top:1px solid #e4e9ee}.ui-dialog .ui-dialog-buttonpane button,.ui-dialog .ui-jqdialog-buttonpane button,.ui-jqdialog .ui-dialog-buttonpane button,.ui-jqdialog .ui-jqdialog-buttonpane button{font-size:14px}.ui-dialog .ui-dialog-titlebar-close,.ui-dialog .ui-jqdialog-titlebar-close,.ui-jqdialog .ui-dialog-titlebar-close,.ui-jqdialog .ui-jqdialog-titlebar-close{border:none;background:0 0;opacity:.4;color:#d15b47;padding:0;top:50%;right:8px!important;text-align:center}.ui-dialog .ui-dialog-titlebar-close:before,.ui-dialog .ui-jqdialog-titlebar-close:before,.ui-jqdialog .ui-dialog-titlebar-close:before,.ui-jqdialog .ui-jqdialog-titlebar-close:before{content:"\f00d";display:inline;font-family:FontAwesome;font-size:16px}.ui-dialog .ui-dialog-titlebar-close:hover,.ui-dialog .ui-jqdialog-titlebar-close:hover,.ui-jqdialog .ui-dialog-titlebar-close:hover,.ui-jqdialog .ui-jqdialog-titlebar-close:hover{opacity:1;text-decoration:none;padding:0}.ui-dialog .ui-dialog-titlebar-close .ui-button-text,.ui-dialog .ui-jqdialog-titlebar-close .ui-button-text,.ui-jqdialog .ui-dialog-titlebar-close .ui-button-text,.ui-jqdialog .ui-jqdialog-titlebar-close .ui-button-text{text-indent:0;visibility:hidden}.ui-dialog .widget-header .ui-dialog-titlebar-close,.ui-dialog .widget-header .ui-jqdialog-titlebar-close,.ui-jqdialog .widget-header .ui-dialog-titlebar-close,.ui-jqdialog .widget-header .ui-jqdialog-titlebar-close{right:10px!important}.ui-accordion .ui-accordion-header{color:#478fca;font-weight:400;background-color:#F9F9F9;border:1px solid #cdd8e3;padding:8px 8px 9px 24px}.ui-accordion .ui-accordion-header:hover{color:#6ea6cc;background-color:#f1f8fd}.ui-accordion .ui-accordion-header.ui-state-active{color:#4c8fbd;background-color:#eef4f9;position:relative;font-weight:700}.ui-accordion .ui-accordion-header .ui-accordion-header-icon{text-indent:0;margin-top:0;position:absolute;left:10px;top:7px}.ui-accordion .ui-accordion-header .ui-accordion-header-icon:before{display:inline;font-family:FontAwesome;font-size:15px;content:"\f0da"}.ui-accordion .ui-accordion-header.ui-state-active .ui-accordion-header-icon:before{content:"\f0d7";font-weight:400}.ui-accordion .ui-accordion-content{border:1px solid #cdd8e3;border-top-width:0;padding:11px 16px}.ui-tabs .ui-tabs-nav{padding:0;border-bottom:1px solid #C5D0DC}.ui-tabs .ui-tabs-nav li.ui-state-default>a{background-color:#F9F9F9;border:1px solid #C5D0DC;border-bottom-width:0;color:#999;line-height:16px;margin-right:-1px;z-index:11;padding:8px 12px;position:relative;top:2px}.ui-tabs .ui-tabs-nav li>a:focus{outline:0}.ui-tabs .ui-tabs-nav li.ui-tabs-active>a{background-color:#FFF;border:1px solid;border-color:#4C8FBD #C5D0DC transparent;border-top-width:2px;-webkit-box-shadow:0 -2px 3px 0 rgba(0,0,0,.15);box-shadow:0 -2px 3px 0 rgba(0,0,0,.15);color:#576373;position:relative;top:1px}.ui-tabs .ui-tabs-panel{border:1px solid #C5D0DC;border-top-width:0;margin:0;left:auto;right:auto;top:auto;bottom:auto}.ui-menu{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;width:150px;-webkit-box-shadow:0 2px 4px rgba(0,0,0,.2);box-shadow:0 2px 4px rgba(0,0,0,.2);background-color:#FFF;border:1px solid rgba(0,0,0,.2);padding:3px}.ui-menu .ui-menu-item a{padding:4px 7px 5px;color:#444;cursor:pointer;-webkit-box-sizing:inherit;-moz-box-sizing:inherit;box-sizing:inherit}.ui-menu .ui-menu-item a .ui-menu-icon{float:right;position:relative;top:0;left:auto;right:auto;bottom:auto;text-indent:0}.ui-menu .ui-menu-item a .ui-menu-icon:before{content:"\f105";font-family:FontAwesome;font-size:14px;display:inline}.ui-menu .ui-menu-item a.ui-state-active,.ui-menu .ui-menu-item a.ui-state-focus,.ui-menu .ui-menu-item a:hover{background-color:#4f99c6;color:#FFF;margin:auto;font-weight:400}.ui-menu .ui-menu-item a.ui-state-active .ui-menu-icon,.ui-menu .ui-menu-item a.ui-state-focus .ui-menu-icon,.ui-menu .ui-menu-item a:hover .ui-menu-icon{color:#FFF}.ui-menu .ui-state-disabled a{color:#999;cursor:default}.ui-menu .ui-state-disabled a.ui-state-active,.ui-menu .ui-state-disabled a.ui-state-focus,.ui-menu .ui-state-disabled a:hover{background-color:#FFF;color:#999}.ui-autocomplete{background-color:#FFF;border:1px solid rgba(0,0,0,.2);-webkit-box-shadow:0 2px 4px rgba(0,0,0,.2);box-shadow:0 2px 4px rgba(0,0,0,.2)}.ui-autocomplete-category{padding:6px;position:relative;background-color:#eef4f9;color:#478fca;font-weight:bolder;border:1px solid #DAE6ED;border-width:1px 0}.ui-spinner-button{border-width:0!important;font-size:10px;height:14px;line-height:14px;width:18px;color:#FFF!important;text-shadow:0 -1px 0 rgba(0,0,0,.25)!important;display:inline-block;position:absolute;text-align:center;padding:0}.ui-spinner-button>.ace-icon{width:18px;display:inline-block}.ui-spinner-up{top:0;right:5px}.ui-spinner-down{bottom:3px;right:5px}.ui-spinner-input{margin-top:0;padding:5px;max-width:100px;font-size:14px}.ui-tooltip{background-color:#444;color:#FFF}.ui-progressbar{background-color:#f5f5f5;height:22px}.ui-progressbar .ui-progressbar-value{margin:0}.ui-progressbar .ui-progressbar-value[class=progress-bar]{background-color:#2a91d8}.ui-jqgrid .ui-jqgrid-view,.ui-jqgrid .ui-paging-info,.ui-jqgrid .ui-pg-selbox,.ui-jqgrid .ui-pg-table{font-size:13px}.ui-jqgrid .ui-jqgrid-title{float:left;margin:8px}.ui-jqgrid .ui-jqgrid-title-rtl{float:right;margin:8px}.ui-jqgrid-view>.ui-jqgrid-titlebar{height:40px;line-height:24px;color:#FFF;background:#307ecc;padding:0;font-size:15px}.ui-jqgrid tr.jqgrow.ui-row-rtl td:last-child{border-right:none;border-left:1px solid #E1E1E1}.ui-jqgrid .ui-jqgrid-hdiv{background-color:#eff3f8;border:1px solid #D3D3D3;border-width:1px 0 0 1px;line-height:15px;font-weight:700;color:#777;text-shadow:none}.ui-jqgrid .ui-jqgrid-htable thead{background-color:#eff3f8}.ui-jqgrid .ui-jqgrid-htable th span.ui-jqgrid-resize{height:45px!important}.ui-jqgrid .ui-jqgrid-htable th div{padding-top:12px;padding-bottom:12px}.ui-jqgrid-hdiv .ui-jqgrid-htable{border-top:1px solid #E1E1E1}.ui-jqgrid-titlebar{position:relative;top:1px;z-index:1}.ui-jqgrid tr.jqgrow,.ui-jqgrid tr.ui-row-ltr,.ui-jqgrid tr.ui-row-rtl{border:none}.ui-jqgrid tr.ui-row-ltr td,.ui-jqgrid tr.ui-row-rtl td{border-bottom:1px solid #E1E1E1;padding:6px 4px;border-color:#E1E1E1}.ui-jqgrid tr.ui-state-highlight.ui-row-ltr td{border-right-color:#C7D3A9}.ui-jqgrid tr.ui-state-highlight.ui-row-rtl td{border-left-color:#C7D3A9}.ui-jqgrid-btable .ui-widget-content.ui-priority-secondary{background-image:none;background-color:#F9F9F9;opacity:1}.ui-jqgrid-btable .ui-widget-content.ui-state-hover{background-image:none;background-color:#EFF4F7;opacity:1}.ui-jqgrid-btable .ui-widget-content.ui-state-highlight{background-color:#E4EFC9}.ui-jqgrid .ui-jqgrid-pager{line-height:15px;height:55px;padding-top:3px!important;padding-bottom:5px!important;background-color:#eff3f8!important;border-bottom:1px solid #E1E1E1!important;border-top:1px solid #E1E1E1!important}.ui-jqgrid .ui-pg-input{font-size:inherit;width:24px;height:20px;line-height:16px;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;text-align:center;padding-top:1px;padding-bottom:1px}.ui-jqgrid .ui-pg-selbox{display:block;height:24px;width:60px;margin:0;padding:1px;line-height:normal}.ui-jqgrid .ui-jqgrid-htable th div{overflow:visible}.ui-jqgrid .ui-pager-control{height:50px;position:relative;padding-left:9px;padding-right:9px}.ui-jqgrid .ui-jqgrid-toppager{height:auto!important;background-color:#eff3f8;border-bottom:1px solid #E1E1E1!important}.ui-jqgrid .jqgrow .editable{max-width:90%;max-width:calc(92%)!important}.ui-pg-table .navtable .ui-corner-all{border-radius:0}.ui-jqgrid .ui-pg-button:hover{padding:1px}.ui-jqgrid .ui-pg-button .ui-separator{margin-left:4px;margin-right:4px;border-color:#C9D4DB}.ui-jqgrid .ui-jqgrid-btable{border-left:1px solid #E1E1E1}.ui-jqgrid .ui-jqgrid-bdiv{border-top:1px solid #E1E1E1}.ui-jqgrid .loading{position:absolute;top:45%;left:45%;width:auto;height:auto;z-index:101;padding:6px;margin:5px;text-align:center;font-weight:700;font-size:12px;background-color:#FFF;border:2px solid #8EB8D1;color:#E2B018}.ui-jqgrid .ui-search-toolbar{border-top:1px solid #E1E1E1}.ui-jqgrid .ui-jqgrid-labels{border-bottom:none;background:#F2F2F2 repeat-x;background-image:-webkit-linear-gradient(top,#f8f8f8 0,#ececec 100%);background-image:-o-linear-gradient(top,#f8f8f8 0,#ececec 100%);background-image:linear-gradient(to bottom,#f8f8f8 0,#ececec 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff8f8f8', endColorstr='#ffececec', GradientType=0);padding:0!important;border-left:1px solid #E1E1E1!important}.ui-jqgrid .ui-jqgrid-labels th{border-right:1px solid #E1E1E1!important;text-align:left!important}.ui-jqgrid-labels th[id*="_cb"]:first-child>div{padding-top:0;text-align:center!important}.ui-jqgrid-sortable{padding-left:4px;font-size:13px;color:#777;font-weight:700}.ui-jqgrid-sortable:hover{color:#547ea8}th[aria-selected=true]{background-image:-webkit-linear-gradient(top,#eff3f8 0,#e3e7ed 100%);background-image:-o-linear-gradient(top,#eff3f8 0,#e3e7ed 100%);background-image:linear-gradient(to bottom,#eff3f8 0,#e3e7ed 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffeff3f8', endColorstr='#ffe3e7ed', GradientType=0)}th[aria-selected=true] .ui-jqgrid-sortable{color:#307ecc}.ui-icon{text-indent:0;color:#307ecc;float:none;right:2px}.rtl .ui-icon{right:auto;left:2px}.ui-grid-ico-sort:before{display:inline;content:"\f0d7";font-family:FontAwesome;font-size:12px}.ui-icon-asc:before{content:"\f0d8"}.ui-state-disabled{color:#BBB}.ui-pg-table>tbody>tr>.ui-pg-button>.ui-icon{display:inline-block;padding:0;width:24px;height:24px;line-height:22px;text-align:center;position:static;float:none;margin:0 2px!important;color:gray;border:1px solid #CCC;background-color:#FFF;border-radius:100%}.ui-pg-table>tbody>tr>.ui-pg-button>.ui-icon:hover{color:#699AB5;border-color:#699AB5}.ui-pg-table>tbody>tr>.ui-pg-button>.ui-icon:before{width:20px;text-align:center;display:inline-block}.ui-pg-table>tbody>tr>.ui-pg-button.ui-state-disabled .ui-icon{color:#B0B0B0;background-color:#F7F7F7;border-color:#DDD;-moz-transform:scale(0.9);-webkit-transform:scale(0.9);-o-transform:scale(0.9);-ms-transform:scale(0.9);transform:scale(0.9)}.ui-jqgrid-btable input,.ui-jqgrid-btable select,.ui-jqgrid-btable textarea{padding:2px;width:auto;max-width:100%;margin-bottom:0}.ui-jqgrid-btable select{padding:1px;height:25px;line-height:25px}.ui-pg-div .ui-icon{display:inline-block;width:18px;float:none;position:static;text-align:center;opacity:.85;-webkit-transition:all .12s;-o-transition:all .12s;transition:all .12s;margin:0 1px;vertical-align:middle;cursor:pointer;font-size:17px}.ui-pg-div .ui-icon:hover{-moz-transform:scale(1.2);-webkit-transform:scale(1.2);-o-transform:scale(1.2);-ms-transform:scale(1.2);transform:scale(1.2);opacity:1;position:static;margin:0 1px}.ui-pg-div .ui-icon:before{font-family:FontAwesome;display:inline}.ui-icon-pencil{color:#478FCA}.ui-icon-pencil:before{content:"\f040"}.ui-icon-trash{color:#DD5A43}.ui-icon-trash:before{content:"\f014"}.ui-icon-disk{color:#69AA46}.ui-icon-disk:before{content:"\f00c"}.ui-icon-cancel{color:#DD5A43}.ui-icon-cancel:before{content:"\f00d"}.ui-jqdialog .ui-jqdialog-content,.ui-jqdialog-content{font-size:13px;padding:4px 0 0}.ui-jqdialog .ui-jqdialog-content .formdata,.ui-jqdialog-content .formdata{font-size:13px;padding:6px 12px}.ui-jqdialog .ui-jqdialog-content .form-view-data,.ui-jqdialog-content .form-view-data{vertical-align:middle;font-size:13px}.ui-jqdialog .ui-jqdialog-content[id*=alertcnt_],.ui-jqdialog-content[id*=alertcnt_]{padding:8px 11px}.ui-jqdialog-content .CaptionTD{font-size:12px;text-align:right;color:#666}.ui-jqdialog-content .FormData{border-bottom:1px dotted #E8E8E8}.ui-jqdialog-content .FormData:last-child{border-bottom:none}.ui-jqdialog-content .FormData>td{padding-top:6px;padding-bottom:6px}.ui-jqdialog-content input.FormElement{width:auto}.ui-jqdialog-content select.FormElement{padding:1px;height:25px;line-height:25px;width:auto}.ui-jqdialog-content td.EditButton{padding:8px}.EditTable{background-color:#eff3f8;border-top:1px solid #D6E1EA!important;padding:8px}.EditTable tr:first-child{display:none}.EditTable .navButton .fm-button{float:none!important;width:auto!important;margin:1px 1px 2px!important;background-color:transparent;border-radius:100%}.EditTable .navButton .fm-button:hover{background-color:transparent}.EditTable .navButton .fm-button:focus{outline:0}.EditTable .navButton .fm-button .ace-icon{display:inline-block;color:#999;border:1px solid #AAA;width:26px;height:26px;line-height:26px;text-align:center;border-radius:100%;background-color:#FFF}.EditTable .navButton .fm-button:hover .ace-icon{color:#699AB5;border-color:#699AB5}.EditTable .navButton .fm-button.ui-state-disabled .ace-icon,.EditTable .navButton .fm-button.ui-state-disabled:hover .ace-icon{color:#BBB;border-color:#CCC;-moz-transform:scale(0.88);-webkit-transform:scale(0.88);-o-transform:scale(0.88);-ms-transform:scale(0.88);transform:scale(0.88)}.FormGrid .EditTable{background-color:#FFF;border-top:none!important;padding:0}.FormGrid .EditTable tr:first-child{display:none}.ui-jqgrid .ui-jqgrid-view button,.ui-jqgrid .ui-jqgrid-view input,.ui-jqgrid .ui-jqgrid-view select,.ui-jqgrid .ui-jqgrid-view textarea{font-size:13px}.ui-jqdialog-content .searchFilter select{padding:1px;height:26px;line-height:26px;width:auto;max-width:95%;margin-bottom:0}.ui-jqdialog-content .searchFilter .input-elm{margin-bottom:0;height:18px;line-height:18px;width:95%!important;padding-left:1px;padding-right:1px;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.ui-jqdialog-content .searchFilter table{margin-left:4px}.ui-jqdialog-content .searchFilter tr td{padding:5px 0}.ui-jqdialog-content .searchFilter .add-group,.ui-jqdialog-content .searchFilter .add-rule,.ui-jqdialog-content .searchFilter .delete-group{margin-left:4px!important;font-size:15px!important}.ui-jqdialog-content .searchFilter .delete-rule{border:none;background-color:#FFF;color:#D15B47;font-size:20px;width:22px;line-height:10px;padding:0;text-shadow:none!important;display:inline-block;-webkit-transition:all .1s;-o-transition:all .1s;transition:all .1s;opacity:.85}.ui-jqdialog-content .searchFilter .delete-rule:hover{-moz-transform:scale(1.1);-webkit-transform:scale(1.1);-o-transform:scale(1.1);-ms-transform:scale(1.1);transform:scale(1.1);color:#B74635;opacity:1}.ui-jqdialog-content .searchFilter .queryresult{margin-bottom:11px}.ui-jqdialog-content .searchFilter .queryresult td.query{padding:6px 11px;border:1px solid #E1E1E1;background-color:#EEE}.ui-jqdialog-content .searchFilter .queryresult td.query:empty{display:none}.ui-state-error{background-color:#f2dede;border:1px solid #ebccd1;color:#a94442;margin:4px 4px 8px;padding:6px 10px;text-shadow:0 1px 0 rgba(255,255,255,.5);font-size:13px}.ui-jqdialog .ui-widget-header{background-image:-webkit-linear-gradient(top,#fff 0,#eee 100%);background-image:-o-linear-gradient(top,#fff 0,#eee 100%);background-image:linear-gradient(to bottom,#fff 0,#eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffeeeeee', GradientType=0);border-image:none;border-bottom:1px solid solid;color:#669FC7;min-height:38px;position:relative}.ui-jqdialog .ui-widget-header .ui-jqdialog-title{line-height:38px;margin:0;padding:0 0 0 12px;text-align:left}.widget-header .ui-jqdialog-title{padding-left:0!important;padding-right:0!important}.ui-jqdialog .ui-widget-header .widget-header{border-bottom:none}.ui-jqdialog .ui-jqdialog-titlebar{border-bottom:1px solid #DDD!important}.fm-button{margin:0 4px}.fm-button:not(.btn){background-color:#abbac3;border-radius:0;box-shadow:none;color:#FFF;cursor:pointer;display:inline-block;font-size:13px;line-height:28px;padding:0 12px 1px;margin:0 8px;position:relative;text-shadow:0 -1px 0 rgba(0,0,0,.25);-webkit-transition:all .15s;-o-transition:all .15s;transition:all .15s;vertical-align:middle}.fm-button.ui-state-default:hover{background-color:#8b9aa3}.ui-jqgrid .ui-jqgrid-htable .ui-search-toolbar th{height:30px;padding-top:2px;white-space:normal}.ui-jqgrid .ui-jqgrid-htable .ui-search-toolbar th div{padding-top:0;padding-bottom:0;height:30px;line-height:26px}.ui-jqgrid .ui-jqgrid-titlebar-close{top:10%;height:auto;padding:0;margin:2px 8px 0 0;text-align:center;border-radius:4px}.ui-jqgrid .ui-jqgrid-titlebar-close:hover{background-color:rgba(255,255,255,.2)}.ui-jqgrid .ui-jqgrid-titlebar-close .ui-icon:before{display:inline-block;font-family:FontAwesome;content:"\f077";color:#FFF}.ui-jqgrid .ui-jqgrid-titlebar-close .ui-icon-circle-triangle-s:before{content:"\f078"}.ui-jqgrid .tree-wrap-ltr{margin:0 4px;float:none;display:inline}.ui-jqgrid .tree-wrap-rtl{margin:2px 4px 0}.ui-jqgrid .ui-subgrid{border-bottom:1px solid #E1E1E1;background-color:#F6FAFF}.ui-jqgrid .ui-subgrid .ui-jqgrid-btable{background-color:#FFF}.ui-jqgrid .ui-subgrid .ui-jqgrid .ui-jqgrid-hdiv{background-color:transparent;margin-top:4px}.ui-jqgrid .ui-subgrid .ui-jqgrid .ui-jqgrid-hdiv .ui-jqgrid-htable .ui-jqgrid-labels{border-bottom:1px solid #E1E1E1;background:#F1F1F1}.ui-jqgrid .ui-subgrid .ui-jqgrid .ui-jqgrid-hdiv .ui-jqgrid-htable th[aria-selected=true]{background:#E5E9EF}.ui-jqgrid .ui-subgrid .ui-jqgrid .ui-jqgrid-hdiv .ui-jqgrid-htable th .ui-jqgrid-sortable{font-size:12px}.ui-jqgrid .ui-subgrid .ui-jqgrid .ui-jqgrid-hdiv .ui-jqgrid-htable th div{padding-top:8px;padding-bottom:8px}.ui-jqgrid .ui-subgrid .ui-jqgrid .ui-jqgrid-hdiv .ui-jqgrid-htable th span.ui-jqgrid-resize{height:36px!important}.ui-jqgrid .ui-subgrid .ui-jqgrid .ui-jqgrid-bdiv{height:auto!important;max-height:150px;margin-bottom:4px;border-top-width:0;border-bottom:1px solid #E1E1E1}.ui-jqgrid .ui-sgcollapsed>a:hover{text-decoration:none}@media only screen and (max-width:767px){.ui-jqgrid .ui-jqgrid-pager{height:90px}.ui-jqgrid .ui-jqgrid-pager>.ui-pager-control{height:85px;padding-top:9px}.ui-jqgrid .ui-jqgrid-pager>.ui-pager-control>.ui-pg-table>tbody>tr>td{vertical-align:top}.ui-jqgrid .ui-jqgrid-pager>.ui-pager-control>.ui-pg-table>tbody>tr>td#grid-pager_center{width:0!important;position:static}.ui-jqgrid .ui-jqgrid-pager>.ui-pager-control>.ui-pg-table>tbody>tr>td#grid-pager_center>.ui-pg-table{margin:36px auto 0;position:absolute;right:0;left:0;text-align:center}}@media only screen and (max-width:767px) and (-webkit-min-device-pixel-ratio:0){.ui-jqgrid .ui-jqgrid-pager>.ui-pager-control>.ui-pg-table>tbody>tr>td#grid-pager_center>.ui-pg-table{width:300px}}.dd{position:relative;display:block;margin:0;padding:0;max-width:600px;list-style:none;line-height:20px}.dd-list{display:block;position:relative;margin:0;padding:0;list-style:none}.dd-list .dd-list{padding-left:30px}.dd-collapsed .dd-list{display:none}.dd-empty,.dd-item,.dd-placeholder{display:block;position:relative;margin:0;padding:0;min-height:20px;line-height:20px}.dd-handle,.dd2-content{display:block;min-height:38px;margin:5px 0;padding:8px 12px;background:#F8FAFF;border:1px solid #DAE2EA;color:#7C9EB2;text-decoration:none;font-weight:700;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.dd-handle:hover,.dd2-content:hover{color:#438EB9;background:#F4F6F7;border-color:#DCE2E8}.dd-handle[class*=btn-],.dd2-content[class*=btn-]{color:#FFF;border:none;padding:9px 12px}.dd-handle[class*=btn-]:hover,.dd2-content[class*=btn-]:hover{opacity:.85;color:#FFF}.dd2-handle+.dd2-content,.dd2-handle+.dd2-content[class*=btn-]{padding-left:44px}.dd-handle[class*=btn-]:hover,.dd2-content[class*=btn-] .dd2-handle[class*=btn-]:hover+.dd2-content[class*=btn-]{color:#FFF}.dd-item>button:hover~.dd-handle,.dd-item>button:hover~.dd2-content{color:#438EB9;background:#F4F6F7;border-color:#DCE2E8}.dd-item>button:hover~.dd-handle[class*=btn-],.dd-item>button:hover~.dd2-content[class*=btn-]{opacity:.85;color:#FFF}.dd2-handle:hover~.dd2-content{color:#438EB9;background:#F4F6F7;border-color:#DCE2E8}.dd2-handle:hover~.dd2-content[class*=btn-]{opacity:.85;color:#FFF}.dd2-item.dd-item>button{margin-left:34px}.dd-item>button{display:block;position:relative;z-index:1;cursor:pointer;float:left;width:25px;height:20px;margin:5px 1px 5px 5px;padding:0;text-indent:100%;white-space:nowrap;overflow:hidden;border:0;background:0 0;font-size:12px;line-height:1;text-align:center;font-weight:700;top:4px;left:1px;color:#707070}.dd-item>button:before{font-family:FontAwesome;content:'\f067';display:block;position:absolute;width:100%;text-align:center;text-indent:0;font-weight:400;font-size:14px}.dd-item>button[data-action=collapse]:before{content:'\f068'}.dd-item>button:hover{color:#707070}.dd-item.dd-colored>button,.dd-item.dd-colored>button:hover{color:#EEE}.dd-empty,.dd-placeholder{margin:5px 0;padding:0;min-height:30px;background:#F0F9FF;border:2px dashed #BED2DB;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.dd-empty{border-color:#AAA;border-style:solid;background-color:#e5e5e5}.dd-dragel{position:absolute;pointer-events:none;z-index:999;opacity:.8}.dd-dragel>li>.dd-handle{color:#4B92BE;background:#F1F5FA;border-color:#D6E1EA;border-left:2px solid #777;position:relative}.dd-dragel>li>.dd-handle[class*=btn-]{color:#FFF}.dd-dragel>.dd-item>.dd-handle{margin-top:0}.dd-list>li[class*=item-]{border-width:0;padding:0}.dd-list>li[class*=item-]>.dd-handle{border-left:2px solid;border-left-color:inherit}.dd-list>li>.dd-handle .sticker{position:absolute;right:0;top:0}.dd-dragel>li>.dd2-handle,.dd2-handle{left:0;top:0;width:36px;margin:0;text-align:center;padding:0!important;line-height:38px;height:38px;background:#EBEDF2;border:1px solid #DEE4EA;cursor:pointer;overflow:hidden;position:absolute;z-index:1}.dd-dragel>li>.dd2-handle,.dd2-handle:hover{background:#E3E8ED}.dd2-content[class*=btn-]{text-shadow:none!important}.dd2-handle[class*=btn-]{text-shadow:none!important;background:rgba(0,0,0,.1)!important;border-right:1px solid #EEE}.dd2-handle[class*=btn-]:hover{background:rgba(0,0,0,.08)!important}.dd-dragel .dd2-handle[class*=btn-]{border-color:transparent #EEE transparent transparent}.dd2-handle.btn-yellow{text-shadow:none!important;background:rgba(0,0,0,.05)!important;border-right:1px solid #FFF}.dd2-handle.btn-yellow:hover{background:rgba(0,0,0,.08)!important}.dd-dragel .dd2-handle.btn-yellow{border-color:transparent #FFF transparent transparent}.dd-item>.dd2-handle .drag-icon{display:none}.dd-dragel>.dd-item>.dd2-handle .drag-icon{display:inline}.dd-dragel>.dd-item>.dd2-handle .normal-icon{display:none}.dropzone{border-radius:0;border:1px solid rgba(0,0,0,.06)}.dropzone .dz-default.dz-message{background-image:none;font-size:24px;text-align:center;line-height:32px;left:0;width:100%;margin-left:auto}.dropzone .dz-default.dz-message span{display:inline;color:#555}.dropzone .dz-default.dz-message span .upload-icon{opacity:.7;filter:alpha(opacity=70);margin-top:8px;cursor:pointer}.dropzone .dz-default.dz-message span .upload-icon:hover{opacity:1;filter:alpha(opacity=100)}.dropzone .dz-preview .dz-error-mark,.dropzone .dz-preview .dz-success-mark,.dropzone-previews .dz-preview .dz-error-mark,.dropzone-previews .dz-preview .dz-success-mark{background-image:none;background-color:rgba(255,255,255,.8);border-radius:100%;text-align:center;line-height:35px}.dropzone .dz-preview .dz-error-mark:before,.dropzone-previews .dz-preview .dz-error-mark:before{font-family:FontAwesome;font-size:30px;color:#DB6262;content:"\f00d"}.dropzone .dz-preview .dz-success-mark:before,.dropzone-previews .dz-preview .dz-success-mark:before{font-family:FontAwesome;font-size:30px;color:#6DA552;content:"\f00c"}.dropzone a.dz-remove,.dropzone-previews a.dz-remove{border:none;border-radius:0;color:#FFF;background:#D15B47;cursor:pointer}.dropzone a.dz-remove:hover,.dropzone-previews a.dz-remove:hover{color:#FFF;background:#B74635}.dropzone .progress,.dropzone-previews .progress{margin-bottom:0}.dropzone .dz-preview.dz-error .progress,.dropzone .dz-preview.dz-success .progress,.dropzone-previews .dz-preview.dz-error .progress,.dropzone-previews .dz-preview.dz-success .progress{display:none}input.tt-hint,input.tt-query,input.typeahead{min-width:175px;font-size:16px;line-height:24px;border:1px solid #CCC;border-radius:0;outline:0}.form-group input.tt-hint,input.tt-hint{background-color:#FFF!important;color:#B0B0B0!important}.tt-dropdown-menu{text-align:left;position:absolute;left:0!important;right:0!important;min-width:175px;margin-top:2px;padding:8px 0;background-color:#FFF;border:1px solid #D0D0D0;border:1px solid rgba(0,0,0,.15);border-radius:0;-webkit-box-shadow:0 2px 4px rgba(0,0,0,.2);box-shadow:0 2px 4px rgba(0,0,0,.2)}.tt-suggestion{padding:3px 12px 4px;font-size:16px;line-height:24px}.tt-suggestion.tt-cursor{color:#FFF;background-color:#4F99C6;cursor:pointer}.tt-suggestion p{margin:0}input.typeahead.scrollable~.tt-dropdown-menu{max-height:200px;overflow-y:auto}.icon-animated-bell{display:inline-block;-moz-animation:ringing 2s 5 ease 1s;-webkit-animation:ringing 2s 5 ease 1s;-o-animation:ringing 2s 5 ease 1s;-ms-animation:ringing 2s 5 ease 1s;animation:ringing 2s 5 ease 1s;-moz-transform-origin:50% 0;-webkit-transform-origin:50% 0;-o-transform-origin:50% 0;-ms-transform-origin:50% 0;transform-origin:50% 0}@-moz-keyframes ringing{0%{-moz-transform:rotate(-15deg)}2%{-moz-transform:rotate(15deg)}4%{-moz-transform:rotate(-18deg)}6%{-moz-transform:rotate(18deg)}8%{-moz-transform:rotate(-22deg)}10%{-moz-transform:rotate(22deg)}12%{-moz-transform:rotate(-18deg)}14%{-moz-transform:rotate(18deg)}16%{-moz-transform:rotate(-12deg)}18%{-moz-transform:rotate(12deg)}20%{-moz-transform:rotate(0deg)}}@-webkit-keyframes ringing{0%{-webkit-transform:rotate(-15deg)}2%{-webkit-transform:rotate(15deg)}4%{-webkit-transform:rotate(-18deg)}6%{-webkit-transform:rotate(18deg)}8%{-webkit-transform:rotate(-22deg)}10%{-webkit-transform:rotate(22deg)}12%{-webkit-transform:rotate(-18deg)}14%{-webkit-transform:rotate(18deg)}16%{-webkit-transform:rotate(-12deg)}18%{-webkit-transform:rotate(12deg)}20%{-webkit-transform:rotate(0deg)}}@-ms-keyframes ringing{0%{-ms-transform:rotate(-15deg)}2%{-ms-transform:rotate(15deg)}4%{-ms-transform:rotate(-18deg)}6%{-ms-transform:rotate(18deg)}8%{-ms-transform:rotate(-22deg)}10%{-ms-transform:rotate(22deg)}12%{-ms-transform:rotate(-18deg)}14%{-ms-transform:rotate(18deg)}16%{-ms-transform:rotate(-12deg)}18%{-ms-transform:rotate(12deg)}20%{-ms-transform:rotate(0deg)}}@keyframes ringing{0%{transform:rotate(-15deg)}2%{transform:rotate(15deg)}4%{transform:rotate(-18deg)}6%{transform:rotate(18deg)}8%{transform:rotate(-22deg)}10%{transform:rotate(22deg)}12%{transform:rotate(-18deg)}14%{transform:rotate(18deg)}16%{transform:rotate(-12deg)}18%{transform:rotate(12deg)}20%{transform:rotate(0deg)}}.icon-animated-vertical{display:inline-block;-moz-animation:vertical 2s 5 ease 2s;-webkit-animation:vertical 2s 5 ease 2s;-o-animation:vertical 2s 5 ease 2s;-ms-animation:vertical 2s 5 ease 2s;animation:vertical 2s 5 ease 2s}@-moz-keyframes vertical{0%{-moz-transform:translate(0,-3px)}4%{-moz-transform:translate(0,3px)}8%{-moz-transform:translate(0,-3px)}12%{-moz-transform:translate(0,3px)}16%{-moz-transform:translate(0,-3px)}20%{-moz-transform:translate(0,3px)}22%{-moz-transform:translate(0,0)}}@-webkit-keyframes vertical{0%{-webkit-transform:translate(0,-3px)}4%{-webkit-transform:translate(0,3px)}8%{-webkit-transform:translate(0,-3px)}12%{-webkit-transform:translate(0,3px)}16%{-webkit-transform:translate(0,-3px)}20%{-webkit-transform:translate(0,3px)}22%{-webkit-transform:translate(0,0)}}@-ms-keyframes vertical{0%{-ms-transform:translate(0,-3px)}4%{-ms-transform:translate(0,3px)}8%{-ms-transform:translate(0,-3px)}12%{-ms-transform:translate(0,3px)}16%{-ms-transform:translate(0,-3px)}20%{-ms-transform:translate(0,3px)}22%{-ms-transform:translate(0,0)}}@keyframes vertical{0%{transform:translate(0,-3px)}4%{transform:translate(0,3px)}8%{transform:translate(0,-3px)}12%{transform:translate(0,3px)}16%{transform:translate(0,-3px)}20%{transform:translate(0,3px)}22%{transform:translate(0,0)}}.icon-animated-hand-pointer{display:inline-block;-moz-animation:hand-pointer 2s 4 ease 2s;-webkit-animation:hand-pointer 2s 4 ease 2s;-o-animation:hand-pointer 2s 4 ease 2s;-ms-animation:hand-pointer 2s 4 ease 2s;animation:hand-pointer 2s 4 ease 2s}@-moz-keyframes hand-pointer{0%{-moz-transform:translate(0,0)}6%{-moz-transform:translate(5px,0)}12%{-moz-transform:translate(0,0)}18%{-moz-transform:translate(5px,0)}24%{-moz-transform:translate(0,0)}30%{-moz-transform:translate(5px,0)}36%{-moz-transform:translate(0,0)}}.icon-animated-wrench{display:inline-block;-moz-animation:wrenching 2.5s 4 ease;-webkit-animation:wrenching 2.5s 4 ease;-o-animation:wrenching 2.5s 4 ease;-ms-animation:wrenching 2.5s 4 ease;animation:wrenching 2.5s 4 ease;-moz-transform-origin:90% 35%;-webkit-transform-origin:90% 35%;-o-transform-origin:90% 35%;-ms-transform-origin:90% 35%;transform-origin:90% 35%}@-moz-keyframes wrenching{0%{-moz-transform:rotate(-12deg)}8%{-moz-transform:rotate(12deg)}10%{-moz-transform:rotate(24deg)}18%,20%{-moz-transform:rotate(-24deg)}28%,30%{-moz-transform:rotate(24deg)}38%,40%{-moz-transform:rotate(-24deg)}48%,50%{-moz-transform:rotate(24deg)}58%,60%{-moz-transform:rotate(-24deg)}68%{-moz-transform:rotate(24deg)}75%{-moz-transform:rotate(0deg)}}@-webkit-keyframes wrenching{0%{-webkit-transform:rotate(-12deg)}8%{-webkit-transform:rotate(12deg)}10%{-webkit-transform:rotate(24deg)}18%,20%{-webkit-transform:rotate(-24deg)}28%,30%{-webkit-transform:rotate(24deg)}38%,40%{-webkit-transform:rotate(-24deg)}48%,50%{-webkit-transform:rotate(24deg)}58%,60%{-webkit-transform:rotate(-24deg)}68%{-webkit-transform:rotate(24deg)}75%{-webkit-transform:rotate(0deg)}}@-o-keyframes wrenching{0%{-o-transform:rotate(-12deg)}8%{-o-transform:rotate(12deg)}10%{-o-transform:rotate(24deg)}18%,20%{-o-transform:rotate(-24deg)}28%,30%{-o-transform:rotate(24deg)}38%,40%{-o-transform:rotate(-24deg)}48%,50%{-o-transform:rotate(24deg)}58%,60%{-o-transform:rotate(-24deg)}68%{-o-transform:rotate(24deg)}75%{-o-transform:rotate(0deg)}}@-ms-keyframes wrenching{0%{-ms-transform:rotate(-12deg)}8%{-ms-transform:rotate(12deg)}10%{-ms-transform:rotate(24deg)}18%,20%{-ms-transform:rotate(-24deg)}28%,30%{-ms-transform:rotate(24deg)}38%,40%{-ms-transform:rotate(-24deg)}48%,50%{-ms-transform:rotate(24deg)}58%,60%{-ms-transform:rotate(-24deg)}68%{-ms-transform:rotate(24deg)}75%{-ms-transform:rotate(0deg)}}@keyframes wrenching{0%{transform:rotate(-12deg)}8%{transform:rotate(12deg)}10%{transform:rotate(24deg)}18%,20%{transform:rotate(-24deg)}28%,30%{transform:rotate(24deg)}38%,40%{transform:rotate(-24deg)}48%,50%{transform:rotate(24deg)}58%,60%{transform:rotate(-24deg)}68%{transform:rotate(24deg)}75%{transform:rotate(0deg)}}@-moz-keyframes blinking{0%{opacity:1}40%{opacity:0}80%{opacity:1}}@-webkit-keyframes blinking{0%{opacity:1}40%{opacity:0}80%{opacity:1}}@-ms-keyframes blinking{0%{opacity:1}40%{opacity:0}80%{opacity:1}}@keyframes blinking{0%{opacity:1}40%{opacity:0}80%{opacity:1}}@-moz-keyframes pulsating{0%{-moz-transform:scale(1)}5%{-moz-transform:scale(0.75)}10%{-moz-transform:scale(1)}15%{-moz-transform:scale(1.25)}20%{-moz-transform:scale(1)}25%{-moz-transform:scale(0.75)}30%{-moz-transform:scale(1)}35%{-moz-transform:scale(1.25)}40%{-moz-transform:scale(1)}}@-webkit-keyframes pulsating{0%{-webkit-transform:scale(1)}5%{-webkit-transform:scale(0.75)}10%{-webkit-transform:scale(1)}15%{-webkit-transform:scale(1.25)}20%{-webkit-transform:scale(1)}25%{-webkit-transform:scale(0.75)}30%{-webkit-transform:scale(1)}35%{-webkit-transform:scale(1.25)}40%{-webkit-transform:scale(1)}}@-ms-keyframes pulsating{0%{-ms-transform:scale(1)}5%{-ms-transform:scale(0.75)}10%{-ms-transform:scale(1)}15%{-ms-transform:scale(1.25)}20%{-ms-transform:scale(1)}25%{-ms-transform:scale(0.75)}30%{-ms-transform:scale(1)}35%{-ms-transform:scale(1.25)}40%{-ms-transform:scale(1)}}@keyframes pulsating{0%{transform:scale(1)}5%{transform:scale(0.75)}10%{transform:scale(1)}15%{transform:scale(1.25)}20%{transform:scale(1)}25%{transform:scale(0.75)}30%{transform:scale(1)}35%{transform:scale(1.25)}40%{transform:scale(1)}}.btn-scroll-up{border-width:0;position:fixed;right:2px;z-index:99;-webkit-transition-duration:.3s;transition-duration:.3s;opacity:0;filter:alpha(opacity=0);bottom:-24px;visibility:hidden}.btn-scroll-up.display{opacity:.7;filter:alpha(opacity=70);bottom:2px;visibility:visible}.btn-scroll-up:hover{opacity:1;filter:alpha(opacity=100)}.btn-scroll-up:focus{outline:0}@media (min-width:768px){.main-container.container>.btn-scroll-up{right:auto;margin-left:714px}}@media (min-width:992px){.main-container.container>.btn-scroll-up{right:auto;margin-left:934px}}@media (min-width:1200px){.main-container.container>.btn-scroll-up{right:auto;margin-left:1134px}}.ace-settings-container{position:absolute;right:0;top:auto;z-index:12}.btn.ace-settings-btn{float:left;display:block;width:42px!important;text-align:center;border-radius:6px 0 0 6px!important;opacity:.55;vertical-align:top;margin:0}.btn.ace-settings-btn.open,.btn.ace-settings-btn:hover{opacity:1}.ace-settings-box{display:block;float:left;max-width:0;max-height:0;overflow:hidden;padding:0;-moz-transform:translate(0,0);-webkit-transform:translate(0,0);-o-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);background-color:#FFF;border:0 solid #ffb34b;-webkit-transition:max-width .15s linear 0s,max-height 0s linear .15s,padding 0s linear .15s,border-width 0s linear .15s;-o-transition:max-width .15s linear 0s,max-height 0s linear .15s,padding 0s linear .15s,border-width 0s linear .15s;transition:max-width .15s linear 0s,max-height 0s linear .15s,padding 0s linear .15s,border-width 0s linear .15s}.ace-settings-box.open{max-width:320px;max-height:1000px;padding:0 14px;border-width:2px;-webkit-transition-delay:0s;-moz-transition-delay:0s;-o-transition-delay:0s;transition-delay:0s}.ace-settings-box.open .ace-settings-item{z-index:auto;min-width:140px}.ace-settings-box .ace-settings-item{margin:6px 0;color:#444;max-height:24px;position:relative;z-index:-1;white-space:nowrap}.ace-settings-box .ace-settings-item>label.lbl{font-size:13px}@media (max-width:480px){.ace-settings-container{text-align:right}.ace-settings-box{float:none!important;text-align:left}.btn.ace-settings-btn{float:none!important;display:inline-block}}@media (max-width:320px){.ace-settings-box>.clearfix>.pull-left,.ace-settings-box>.clearfix>.pull-right{float:none!important}}.grid2,.grid3,.grid4{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin:0 1%;padding:0 2%;float:left;border-left:1px solid #E3E3E3}.grid2:first-child,.grid3:first-child,.grid4:first-child{border-left:none}.grid2{width:48%}.grid3{width:31.33%}.grid4{width:23%;padding:0 1%}.draggable-placeholder{border:2px dashed #D9D9D9!important;background-color:#F7F7F7!important}.easy-pie-chart,.easyPieChart{position:relative;text-align:center}.easy-pie-chart canvas,.easyPieChart canvas{position:absolute;top:0;left:0}.knob-container{direction:ltr;text-align:left}.tags{display:inline-block;padding:4px 6px;color:#777;vertical-align:middle;background-color:#FFF;border:1px solid #d5d5d5;width:206px}.tags:hover{border-color:#b5b5b5}.tags-hover,.tags-hover:hover{border-color:#f59942;outline:0}.tags[class*=span]{float:none;margin-left:0}.tags input[type=text],.tags input[type=text]:focus{border:none;display:inline;outline:0;margin:0;padding:0;line-height:18px;-webkit-box-shadow:none;box-shadow:none;width:100%}.tags .tag{display:inline-block;position:relative;font-size:13px;font-weight:400;vertical-align:baseline;white-space:nowrap;background-color:#91b8d0;color:#FFF;text-shadow:1px 1px 1px rgba(0,0,0,.15);padding:4px 22px 5px 9px;margin-bottom:3px;margin-right:3px;-webkit-transition:all .2s;-o-transition:all .2s;transition:all .2s}.tags .tag:empty{display:none}.tags .tag-important{background-color:#d15b47}.tags .tag-warning{background-color:#ffb752}.tags .tag-success{background-color:#87b87f}.tags .tag-info{background-color:#6fb3e0}.tags .tag-inverse{background-color:#555}.tags .tag .close{font-size:15px;line-height:20px;opacity:1;filter:alpha(opacity=100);color:#FFF;text-shadow:none;float:none;position:absolute;right:0;top:0;bottom:0;width:18px;text-align:center}.tags .tag .close:hover{background-color:rgba(0,0,0,.2)}.page-content>.row .col-lg-12,.page-content>.row .col-md-12,.page-content>.row .col-sm-12,.page-content>.row .col-xs-12{float:left;max-width:100%}.col-xs-reset{width:auto;padding-left:0;padding-right:0;float:none!important}@media (min-width:768px){.col-sm-reset{width:auto;padding-left:0;padding-right:0;float:none!important}}@media (min-width:992px){.col-md-reset{width:auto;padding-left:0;padding-right:0;float:none!important}}@media (min-width:1200px){.col-lg-reset{width:auto;padding-left:0;padding-right:0;float:none!important}}.jqstooltip,.legendColorBox div{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.legendLabel{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;height:22px;padding-left:2px;font-size:10px}@media only screen and (max-width:991px){body{overflow-x:hidden}}.navbar-fixed-top+.main-container{padding-top:45px}@media (max-width:479px){.navbar-fixed-top+.main-container{padding-top:90px}.navbar-fixed-top.navbar-collapse+.main-container{padding-top:45px}}@media only screen and (max-width:360px){.grid2,.grid3,.grid4{float:none;display:block;width:96%;border-left-width:0;position:relative;margin-bottom:11px;border-bottom:1px solid #E3E3E3;padding-bottom:4px}.grid2>[class*=pull-],.grid3>[class*=pull-],.grid4>[class*=pull-]{float:none!important;display:inline-block;position:absolute;right:11px;top:0;margin-top:0}.grid2:last-child,.grid3:last-child,.grid4:last-child{border-bottom-width:0}}@media only screen and (max-width:480px){.hidden-480{display:none!important}}@media only screen and (max-width:320px){.hidden-320{display:none!important}}.no-skin .navbar .navbar-toggle{background-color:#75B3D7}.no-skin .navbar .navbar-toggle:focus{background-color:#75B3D7;border-color:transparent}.no-skin .navbar .navbar-toggle:hover{background-color:#61a8d1;border-color:rgba(255,255,255,.1)}.no-skin .navbar .navbar-toggle.display,.no-skin .navbar .navbar-toggle[data-toggle=collapse]:not(.collapsed){background-color:#4d9dcc;box-shadow:inset 1px 1px 2px 0 rgba(0,0,0,.25);border-color:rgba(255,255,255,.35)}.no-skin .sidebar{background-color:#f2f2f2;border-style:solid;border-color:#ccc;border-width:0 1px 0 0}.no-skin .nav-list .open>a,.no-skin .nav-list .open>a:focus,.no-skin .nav-list .open>a:hover{background-color:#fafafa}.no-skin .nav-list>li{border-color:#e5e5e5}.no-skin .nav-list>li>a{background-color:#f8f8f8;color:#585858}.no-skin .nav-list>li>a:focus{background-color:#f8f8f8;color:#1963aa}.no-skin .nav-list>li:hover>a{background-color:#fff;color:#266cad}.no-skin .nav-list>li.open>a{background-color:#fafafa;color:#1963aa}.no-skin .nav-list>li.active>a{font-weight:700;color:#2b7dbc}.no-skin .nav-list>li.active>a,.no-skin .nav-list>li.active>a:focus,.no-skin .nav-list>li.active>a:hover{background-color:#fff}.no-skin .nav-list>li .submenu{background-color:#fff;border-color:#e5e5e5}.no-skin .nav-list>li .submenu>li>a{border-top-color:#e4e4e4;background-color:#fff;color:#616161}.no-skin .nav-list>li .submenu>li>a:hover{color:#4b88b7;background-color:#f1f5f9}.no-skin .nav-list>li .submenu>li.active>a{color:#2b7dbc}.no-skin .nav-list>li .submenu>li.active>a>.menu-icon{color:#c86139}.no-skin .nav-list>li .submenu>li.active.open>a>.menu-icon{color:inherit}@media only screen and (min-width:992px){.no-skin .nav-list>li .submenu>li.active.hover>a.dropdown-toggle>.menu-icon{color:inherit}}.no-skin .nav-list>li .submenu>li.active:not(.open)>a{background-color:#f5f7fa}.no-skin .nav-list>li .submenu>li.active:not(.open)>a:hover{background-color:#f1f5f9}.no-skin .nav-list>li>.submenu .open>a,.no-skin .nav-list>li>.submenu .open>a:focus,.no-skin .nav-list>li>.submenu .open>a:hover{border-color:#e4e4e4}.no-skin .nav-list>li>.submenu li>.submenu>li a{color:#757575}.no-skin .nav-list>li>.submenu li>.submenu>li a:hover{color:#4b88b7;background-color:#f1f5f9}.no-skin .nav-list>li>.submenu li.open>a,.no-skin .nav-list>li>.submenu li>.submenu li.active>a,.no-skin .nav-list>li>.submenu li>.submenu li.open>a{color:#4b88b7}.no-skin .nav-list>li>.submenu:before,.no-skin .nav-list>li>.submenu>li:before{border-color:#9dbdd6}.no-skin .nav-list>li.active>.submenu:before,.no-skin .nav-list>li.active>.submenu>li:before{border-color:#8eb3d0}.no-skin .sidebar-toggle{background-color:#f3f3f3;border-color:#e0e0e0}.no-skin .sidebar-toggle>.ace-icon{border-color:#bbb;color:#aaa;background-color:#fff}.no-skin .sidebar-shortcuts{background-color:#fafafa}.no-skin .sidebar-fixed .sidebar-shortcuts{border-color:#ddd}.no-skin .sidebar-shortcuts-mini{background-color:#fff}.no-skin .nav-list li>.arrow:before{border-right-color:#B8B8B8;-moz-border-right-colors:#B8B8B8;border-width:10px 10px 10px 0;left:-11px}.no-skin .nav-list li>.arrow:after{border-right-color:#fff;-moz-border-right-colors:#fff;border-width:10px 10px 10px 0;left:-10px}.no-skin .nav-list>li.pull_up>.arrow:after{border-right-color:#fff!important;-moz-border-right-colors:#fff!important;border-width:10px 10px 10px 0!important;left:-10px!important}.no-skin .nav-list>li.pull_up>.arrow:before{border-width:10px 10px 10px 0!important;left:-11px!important}.no-skin .nav-list li.active>a:after{border-right-color:#2b7dbc;-moz-border-right-colors:#2b7dbc}.no-skin .nav-list>li.active:after{display:block;content:"";position:absolute;right:-2px;top:-1px;bottom:0;z-index:1;border:2px solid;border-width:0 2px 0 0;border-color:#2b7dbc}.no-skin .sidebar-scroll .nav-list>li.active:after{right:0}@media only screen and (max-width:991px){.no-skin .sidebar.responsive .nav-list>li.active.open>a:after{display:block}}.no-skin .sidebar.menu-min .nav-list>li>a>.menu-text{background-color:#f5f5f5;-webkit-box-shadow:2px 1px 2px 0 rgba(0,0,0,.1);box-shadow:2px 1px 2px 0 rgba(0,0,0,.1);border-color:#ccc}.no-skin .sidebar.menu-min .nav-list>li>a.dropdown-toggle>.menu-text{-webkit-box-shadow:2px 2px 2px 0 rgba(0,0,0,.1);box-shadow:2px 2px 2px 0 rgba(0,0,0,.1)}.no-skin .sidebar.menu-min .nav-list>li.active>.submenu{border-left-color:#83b6d1}.no-skin .sidebar.menu-min .nav-list>li>.submenu{background-color:#fff;border:1px solid #ccc;border-top-color:#e6e6e6;-webkit-box-shadow:2px 2px 2px 0 rgba(0,0,0,.1);box-shadow:2px 2px 2px 0 rgba(0,0,0,.1)}.no-skin .sidebar.menu-min .nav-list>li>.arrow:after{border-right-color:#f5f5f5;-moz-border-right-colors:#f5f5f5;border-width:8px 8px 8px 0;left:-8px}.no-skin .sidebar.menu-min .nav-list>li>.arrow:before{border-width:8px 8px 8px 0;left:-9px}.no-skin .sidebar.menu-min .nav-list>li.active>.arrow:before{border-right-color:#5a9ec2;-moz-border-right-colors:#5a9ec2}.no-skin .sidebar.menu-min .nav-list>li.active>a>.menu-text{border-left-color:#83b6d1}.no-skin .sidebar.menu-min .sidebar-shortcuts-large{background-color:#fff;-webkit-box-shadow:2px 1px 2px 0 rgba(0,0,0,.1);box-shadow:2px 1px 2px 0 rgba(0,0,0,.1);border-color:#ccc}.no-skin .sidebar.menu-min .sidebar-toggle>.ace-icon{border-color:#b1b1b1}@media (max-width:991px){.no-skin .sidebar.responsive-min .nav-list>li>a>.menu-text{background-color:#f5f5f5;-webkit-box-shadow:2px 1px 2px 0 rgba(0,0,0,.1);box-shadow:2px 1px 2px 0 rgba(0,0,0,.1);border-color:#ccc}.no-skin .sidebar.responsive-min .nav-list>li>a.dropdown-toggle>.menu-text{-webkit-box-shadow:2px 2px 2px 0 rgba(0,0,0,.1);box-shadow:2px 2px 2px 0 rgba(0,0,0,.1)}.no-skin .sidebar.responsive-min .nav-list>li.active>.submenu{border-left-color:#83b6d1}.no-skin .sidebar.responsive-min .nav-list>li>.submenu{background-color:#fff;border:1px solid #ccc;border-top-color:#e6e6e6;-webkit-box-shadow:2px 2px 2px 0 rgba(0,0,0,.1);box-shadow:2px 2px 2px 0 rgba(0,0,0,.1)}.no-skin .sidebar.responsive-min .nav-list>li>.arrow:after{border-right-color:#f5f5f5;-moz-border-right-colors:#f5f5f5;border-width:8px 8px 8px 0;left:-8px}.no-skin .sidebar.responsive-min .nav-list>li>.arrow:before{border-width:8px 8px 8px 0;left:-9px}.no-skin .sidebar.responsive-min .nav-list>li.active>.arrow:before{border-right-color:#5a9ec2;-moz-border-right-colors:#5a9ec2}.no-skin .sidebar.responsive-min .nav-list>li.active>a>.menu-text{border-left-color:#83b6d1}.no-skin .sidebar.responsive-min .sidebar-shortcuts-large{background-color:#fff;-webkit-box-shadow:2px 1px 2px 0 rgba(0,0,0,.1);box-shadow:2px 1px 2px 0 rgba(0,0,0,.1);border-color:#ccc}.no-skin .sidebar.responsive-min .sidebar-toggle>.ace-icon{border-color:#b1b1b1}}@media only screen and (min-width:992px){.no-skin .nav-list li.hover>.submenu{-webkit-box-shadow:2px 1px 2px 0 rgba(0,0,0,.1);box-shadow:2px 1px 2px 0 rgba(0,0,0,.1);border-color:#ccc}.no-skin .nav-list li.hover>.submenu>li.active>a{background-color:#f5f5f5}.no-skin .nav-list li.hover>.submenu>li:hover>a{background-color:#eef3f7;color:#2e7db4}}@media only screen and (min-width:992px) and (max-width:991px){.no-skin .sidebar.navbar-collapse .nav-list li li.hover.active.open>a,.no-skin .sidebar.navbar-collapse .nav-list li li.hover:hover>a{background-color:#fff}.no-skin .sidebar.navbar-collapse .nav-list li li.hover.open.active>a:hover,.no-skin .sidebar.navbar-collapse .nav-list li li.hover.open>a:hover,.no-skin .sidebar.navbar-collapse .nav-list li li.hover>a:hover{background-color:#f1f5f9}.no-skin .sidebar.navbar-collapse .nav-list>li .submenu>li.active.hover>a.dropdown-toggle>.menu-icon{color:#c86139}.no-skin .sidebar.navbar-collapse .nav-list>li .submenu>li.active.open.hover>a.dropdown-toggle>.menu-icon{color:inherit}}@media only screen and (min-width:992px){.no-skin .sidebar.navbar-collapse .nav-list>li.open.hover:not(:hover):not(:focus):not(.active)>a{color:#585858}.no-skin .sidebar.navbar-collapse .nav-list>li.open.hover:not(:hover):not(:focus):not(.active)>a>.arrow{color:inherit}.no-skin .sidebar.navbar-collapse .nav-list>li.open.hover:hover>a{background-color:#fff}.no-skin .sidebar.navbar-collapse .nav-list>li>.submenu li.open.hover:not(:hover):not(:focus):not(.active)>a{color:#616161}.no-skin .sidebar.navbar-collapse .nav-list>li>.submenu li.open.hover:not(:hover):not(:focus):not(.active)>a>.arrow{color:inherit}}@media only screen and (min-width:992px) and (max-width:991px){.no-skin .sidebar.navbar-collapse .nav-list li.hover>.submenu{border-top-color:#e5e5e5;background-color:#fff}.no-skin .nav-list li.hover>.submenu>li.active:not(.open)>a{background-color:#f5f7fa}.no-skin .nav-list li.hover>.submenu>li.active:not(.open)>a:hover{background-color:#f1f5f9}}@media only screen and (min-width:992px){.no-skin .sidebar.h-sidebar{background-color:#f8f8f8}.no-skin .sidebar.h-sidebar:before{background-color:#e4e4e4;-webkit-box-shadow:0 -1px 1px 0 rgba(0,0,0,.05) inset;box-shadow:0 -1px 1px 0 rgba(0,0,0,.05) inset}.no-skin .sidebar.h-sidebar .nav-list>li:hover{border-color:#cedde5}.no-skin .sidebar.h-sidebar .nav-list>li.active{border-color:#79b0ce}.no-skin .sidebar.h-sidebar .nav-list>li.active:before{background-color:#2b7dbc}.no-skin .sidebar.h-sidebar .nav-list>li.active>a:after{border-width:0 0 3px;border-color:transparent transparent #FFF;left:0;right:0;top:auto;bottom:-3px}.no-skin .sidebar.h-sidebar .sidebar-shortcuts-large{background-color:#FFF;border-color:#CCC;-webkit-box-shadow:2px 1px 2px 0 rgba(0,0,0,.1);box-shadow:2px 1px 2px 0 rgba(0,0,0,.1)}.no-skin .sidebar.h-sidebar .sidebar-shortcuts-large:after{border-bottom-color:#FFF;-moz-border-bottom-colors:#FFF}.no-skin .sidebar.h-sidebar .nav-list>li.hover>.submenu{border-color:#ccc}.no-skin .sidebar.h-sidebar .nav-list>li.hover>.arrow:after{border-color:transparent transparent #FFF;-moz-border-right-colors:none;-moz-border-top-colors:none;-moz-border-left-colors:none;-moz-border-bottom-colors:#FFF}.no-skin .sidebar.h-sidebar .nav-list>li.hover>.arrow:before{border-color:transparent transparent #B8B8B8;-moz-border-right-colors:none;-moz-border-top-colors:none;-moz-border-left-colors:none;-moz-border-bottom-colors:#B8B8B8}}@media only screen and (max-width:991px){.no-skin .sidebar{border-width:0 1px 1px 0;border-top-color:#d6d6d6}.no-skin .menu-toggler+.sidebar.responsive{border-top-width:1px}.no-skin .sidebar.responsive-min{border-width:0 1px 0 0}.no-skin .sidebar.navbar-collapse{border-width:0;border-bottom-width:1px!important;border-bottom-color:#ccc;-webkit-box-shadow:0 2px 2px rgba(0,0,0,.1)!important;box-shadow:0 2px 2px rgba(0,0,0,.1)!important}.no-skin .sidebar.navbar-collapse.menu-min .nav-list>li>.submenu{background-color:#fff}}.no-skin .sidebar-scroll .sidebar-shortcuts{border-bottom-color:#ddd}.no-skin .sidebar-scroll .sidebar-toggle{border-top-color:#ddd}.no-skin .main-container .menu-toggler{background-color:#444}.no-skin .main-container .menu-toggler:before{border-top-color:#87b87f;border-bottom-color:#6fb3e0}.no-skin .main-container .menu-toggler:after{border-top-color:#ffa24d;border-bottom-color:#d15b47}.no-skin .main-container .menu-toggler>.toggler-text{border-top-color:#444;-moz-border-top-colors:#444}.no-skin .nav-list>li.disabled:before{display:none!important}.no-skin .nav-list>li.disabled>a{background-color:#ebebeb!important;color:#656565!important}.no-skin .nav-list li .submenu>li.disabled>a,.no-skin .nav-list li.disabled .submenu>li>a{background-color:#f2f2f2!important;color:#7a7a7a!important;cursor:not-allowed!important}.no-skin .nav-list li .submenu>li.disabled>a>.menu-icon,.no-skin .nav-list li.disabled .submenu>li>a>.menu-icon{display:none}.nav-list li li.highlight.active>a:after,.nav-list li li.highlight.active>a:before,.nav-list li.highlight li.active>a:after,.nav-list li.highlight li.active>a:before{display:none!important}.nav-list>li.highlight.active>a:after,.nav-list>li.highlight.active>a:before{display:block!important}.sidebar-scroll .nav-list>li.active.highlight>a:after,.sidebar-scroll .nav-list>li.active.highlight>a:before{display:none!important}.no-skin .nav-list>li.highlight.active,.no-skin .nav-list>li.highlight:hover{border-color:#c8d8e2}.no-skin .nav-list>li.highlight.active+li,.no-skin .nav-list>li.highlight:hover+li{border-top-color:#c8d8e2}.no-skin .nav-list>li.highlight.active>a,.no-skin .nav-list>li.highlight:hover>a{background-color:#FFF}.no-skin .nav-list>li.highlight.active:after{display:none}.no-skin .nav-list>li.highlight.active:before{display:block;background-color:#4f90c2}.no-skin .nav-list>li.highlight.active>a{background-color:#f2f6f9!important}.no-skin .nav-list>li.highlight.active>a:after,.no-skin .nav-list>li.highlight.active>a:before{display:block;content:"";position:absolute;top:-1px;right:-10px;bottom:auto;z-index:1;border-style:solid;border-width:20px 0 21px 10px;border-color:transparent}.no-skin .nav-list>li.highlight.active>a:before{border-left-color:#a0bccd;-moz-border-left-colors:#a0bccd;right:-11px}.no-skin .nav-list>li.highlight.active>a:after{border-left-color:#f2f6f9;-moz-border-left-colors:#f2f6f9}.no-skin .nav-list li li.highlight.active>a{background-color:#f2f6f9}.no-skin .nav-list li li.highlight.active.open>a{background-color:#FFF}.no-skin .nav-list li li.highlight.active.open>a:hover{background-color:#f1f5f9}@media (min-width:992px){.no-skin .sidebar.h-sidebar .nav-list>li.highlight.active>a:after{display:block;content:"";position:absolute;top:auto;right:auto;bottom:-2px;left:50%;margin-left:-7px;border-color:transparent transparent #FFF;-moz-border-right-colors:none;-moz-border-left-colors:none;-moz-border-top-colors:none;border-width:8px 7px;-moz-border-bottom-colors:#FFF}.no-skin .sidebar.h-sidebar .nav-list>li.highlight.active>a:before{content:"";position:absolute;display:block;top:auto;right:auto;bottom:-1px;left:50%;margin-left:-7px;border-width:8px;border-color:transparent transparent #74add7;-moz-border-right-colors:none;-moz-border-left-colors:none;-moz-border-top-colors:none;-moz-border-bottom-colors:#74add7}.no-skin .sidebar.h-sidebar .nav-list>li.highlight.active:hover>a:after,.no-skin .sidebar.h-sidebar .nav-list>li.highlight.active:hover>a:before{display:none}}@media (min-width:992px){.sidebar.compact .nav-list li.highlight.active>a:after,.sidebar.compact .nav-list li.highlight.active>a:before{display:none!important}}@media (min-width:992px){.sidebar.h-sidebar .nav-list li.highlight.active>a:after,.sidebar.h-sidebar .nav-list li.highlight.active>a:before{display:block!important;border-width:8px!important;-moz-border-left-colors:none!important;-moz-border-right-colors:none!important;border-left-color:transparent!important;border-right-color:transparent!important}.sidebar.h-sidebar .nav-list>li.highlight.active:hover>a:after,.sidebar.h-sidebar .nav-list>li.highlight.active:hover>a:before{display:none!important}}.sidebar.menu-min .nav-list>li.highlight.active>a:after,.sidebar.menu-min .nav-list>li.highlight.active>a:before{display:block!important;top:-1px;border-width:20px 0 21px 10px}@media (max-width:991px){.sidebar.responsive-min .nav-list>li.highlight.active>a:after,.sidebar.responsive-min .nav-list>li.highlight.active>a:before{display:block!important;top:-1px;border-width:20px 0 21px 10px}}.onpage-help-backdrop{position:absolute;z-index:99990;top:0;bottom:0;left:0;right:0;background-color:#000;filter:alpha(opacity=5);background-color:rgba(0,0,0,.05)}.onpage-help-section{display:block;position:absolute;z-index:100000;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#4DFFFFFF', endColorstr='#4DFFFFFF', GradientType=0);background-color:rgba(255,255,255,.3);border:1px dashed #8BBCD3;border-radius:4px;transition:background-color .2s,border-color .2s;-webkit-transition:background-color .2s,border-color .2s;text-align:center;vertical-align:middle;outline:0!important}.onpage-help-section>.ie-hover-fix{display:block;position:absolute;top:0;bottom:0;left:0;right:0;background-color:#FFF;filter:alpha(opacity=1)}.onpage-help-section:active,.onpage-help-section:focus{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#33C9D8EA', endColorstr='#33C9D8EA', GradientType=0);background-color:rgba(201,216,234,.2);border-color:#77ACC4}.onpage-help-section:hover{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#66C9D8EA', endColorstr='#66C9D8EA', GradientType=0);background-color:rgba(201,216,234,.4);border-color:#77ACC4;border-style:solid}.onpage-help-section>.help-icon-1{font-size:36px;display:inline-block;position:absolute;z-index:1;top:50%;left:50%;transform:translate(-50%,-50%);-webkit-transform:translate(-50%,-50%);opacity:0;filter:alpha(opacity=0);color:#FFF;text-shadow:0 0 2px #000;background-color:#85B8DB;border:2px solid #FFF;border-radius:100%;box-shadow:0 0 2px 1px rgba(0,0,0,.4);width:48px;height:48px;line-height:46px;transition:opacity .2s;-webkit-transition:opacity .2s}.onpage-help-section:active>.help-icon-1,.onpage-help-section:focus>.help-icon-1{opacity:.5}.onpage-help-section:hover>.help-icon-1{opacity:1;filter:alpha(opacity=100)}.onpage-help-section.help-section-small>.help-icon-1{font-size:18px;width:28px;height:28px;line-height:26px;border-radius:12px}.onpage-help-section.help-section-smaller>.help-icon-1{font-size:14px;width:20px;height:20px;line-height:17px;border-radius:8px}.onpage-help-section>.help-icon-2{position:absolute;z-index:2;left:-4px;top:-4px;width:18px;height:18px;line-height:16px;display:block;font-size:16px;color:orange;background-color:#FFF;border:1px solid orange;border-radius:4px;opacity:1;transition:all .2s;-webkit-transition:all .2s}.onpage-help-section:hover>.help-icon-2{color:#59A34E;border-color:#59A34E;transform:scale(1.25);-webkit-transform:scale(1.25)}.onpage-help-modal{z-index:100010}.onpage-help-modal+.modal-backdrop{z-index:100009}.onpage-help-modal-buttons button{border-radius:100%;border-width:2px!important}.onpage-help-modal-buttons button:focus{outline:0!important}.onpage-help-modal-buttons button.disabled{transform:scale(0.9);-webkit-transform:scale(0.9)}.onpage-help-content{max-width:800px;margin:0 auto}.code-modal.onpage-help-modal .modal-dialog{margin-top:6px;margin-bottom:6px}.code-modal.onpage-help-modal .modal-header{padding-top:6px;padding-bottom:6px}.code-modal.onpage-help-modal .modal-body{padding:10px 12px}.onpage-help-modal pre{border-width:0;box-shadow:none;border-radius:0;margin-top:8px}.onpage-help-modal .modal-title code{font-size:13px}.onpage-help-modal .modal-body{font-size:14px}@media print{.navbar,.sidebar{display:none!important}.main-content{margin-left:0!important;margin-right:0!important}.main-content .nav-search{display:none!important}.main-content .breadcrumbs{float:right;border-width:0!important}.main-content .breadcrumbs .breadcrumb>li+li:before{content:"/"}.main-content .breadcrumbs .breadcrumb .home-icon{display:none}.ace-settings-container{display:none!important}.footer{width:100%;height:auto;position:relative}.footer .footer-inner,.footer .footer-inner .footer-content{width:100%}.btn-scroll-up{display:none!important}.btn,.btn.btn-app{background:0 0!important;border-width:1px!important;border-radius:0!important;color:#555!important}.label{border:1px solid #666!important}.label[class*=arrowed]:after,.label[class*=arrowed]:before{display:none!important}} \ No newline at end of file diff --git a/filer/static/admin/libs/bootstrap/config.rb b/filer/static/admin/libs/bootstrap/config.rb new file mode 100644 index 000000000..d6c05c2f3 --- /dev/null +++ b/filer/static/admin/libs/bootstrap/config.rb @@ -0,0 +1,23 @@ +# Require any additional compass plugins here. + +http_path = "/" +css_dir = "css" +sass_dir = "sass" +images_dir = "images" +javascripts_dir = "javascripts" + +# You can select your preferred output style here (can be overridden via the command line): +# output_style = :expanded or :nested or :compact or :compressed + +# To enable relative paths to assets via compass helper functions. Uncomment: +# relative_assets = true + +# To disable debugging comments that display the original location of your selectors. Uncomment: +# line_comments = false + + +# If you prefer the indented syntax, you might want to regenerate this +# project again passing --syntax sass, or you can uncomment this: +# preferred_syntax = :sass +# and then run: +# sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass diff --git a/filer/static/admin/libs/bootstrap/css/bootstrap.css b/filer/static/admin/libs/bootstrap/css/bootstrap.css new file mode 100644 index 000000000..04ee97837 --- /dev/null +++ b/filer/static/admin/libs/bootstrap/css/bootstrap.css @@ -0,0 +1,8075 @@ +@charset "UTF-8"; +/* Bootstrap v3.2.0 */ +/*! normalize.css v3.0.1 | MIT License | git.io/normalize */ +/* line 9, ../sass/bootstrap/_normalize.scss */ +html { + font-family: sans-serif; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; +} + +/* line 19, ../sass/bootstrap/_normalize.scss */ +body { + margin: 0; +} + +/* line 32, ../sass/bootstrap/_normalize.scss */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +nav, +section, +summary { + display: block; +} + +/* line 52, ../sass/bootstrap/_normalize.scss */ +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} + +/* line 65, ../sass/bootstrap/_normalize.scss */ +audio:not([controls]) { + display: none; + height: 0; +} + +/* line 75, ../sass/bootstrap/_normalize.scss */ +[hidden], +template { + display: none; +} + +/* line 87, ../sass/bootstrap/_normalize.scss */ +a { + background: transparent; +} + +/* line 95, ../sass/bootstrap/_normalize.scss */ +a:active, +a:hover { + outline: 0; +} + +/* line 107, ../sass/bootstrap/_normalize.scss */ +abbr[title] { + border-bottom: 1px dotted; +} + +/* line 115, ../sass/bootstrap/_normalize.scss */ +b, +strong { + font-weight: bold; +} + +/* line 124, ../sass/bootstrap/_normalize.scss */ +dfn { + font-style: italic; +} + +/* line 133, ../sass/bootstrap/_normalize.scss */ +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/* line 142, ../sass/bootstrap/_normalize.scss */ +mark { + background: #ff0; + color: #000; +} + +/* line 151, ../sass/bootstrap/_normalize.scss */ +small { + font-size: 80%; +} + +/* line 159, ../sass/bootstrap/_normalize.scss */ +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +/* line 167, ../sass/bootstrap/_normalize.scss */ +sup { + top: -0.5em; +} + +/* line 171, ../sass/bootstrap/_normalize.scss */ +sub { + bottom: -0.25em; +} + +/* line 182, ../sass/bootstrap/_normalize.scss */ +img { + border: 0; +} + +/* line 190, ../sass/bootstrap/_normalize.scss */ +svg:not(:root) { + overflow: hidden; +} + +/* line 201, ../sass/bootstrap/_normalize.scss */ +figure { + margin: 1em 40px; +} + +/* line 209, ../sass/bootstrap/_normalize.scss */ +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} + +/* line 219, ../sass/bootstrap/_normalize.scss */ +pre { + overflow: auto; +} + +/* line 227, ../sass/bootstrap/_normalize.scss */ +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} + +/* line 250, ../sass/bootstrap/_normalize.scss */ +button, +input, +optgroup, +select, +textarea { + color: inherit; + font: inherit; + margin: 0; +} + +/* line 264, ../sass/bootstrap/_normalize.scss */ +button { + overflow: visible; +} + +/* line 275, ../sass/bootstrap/_normalize.scss */ +button, +select { + text-transform: none; +} + +/* line 288, ../sass/bootstrap/_normalize.scss */ +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} + +/* line 300, ../sass/bootstrap/_normalize.scss */ +button[disabled], +html input[disabled] { + cursor: default; +} + +/* line 309, ../sass/bootstrap/_normalize.scss */ +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/* line 320, ../sass/bootstrap/_normalize.scss */ +input { + line-height: normal; +} + +/* line 332, ../sass/bootstrap/_normalize.scss */ +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + padding: 0; +} + +/* line 344, ../sass/bootstrap/_normalize.scss */ +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/* line 355, ../sass/bootstrap/_normalize.scss */ +input[type="search"] { + -webkit-appearance: textfield; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} + +/* line 368, ../sass/bootstrap/_normalize.scss */ +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/* line 377, ../sass/bootstrap/_normalize.scss */ +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/* line 388, ../sass/bootstrap/_normalize.scss */ +legend { + border: 0; + padding: 0; +} + +/* line 397, ../sass/bootstrap/_normalize.scss */ +textarea { + overflow: auto; +} + +/* line 406, ../sass/bootstrap/_normalize.scss */ +optgroup { + font-weight: bold; +} + +/* line 417, ../sass/bootstrap/_normalize.scss */ +table { + border-collapse: collapse; + border-spacing: 0; +} + +/* line 422, ../sass/bootstrap/_normalize.scss */ +td, +th { + padding: 0; +} + +@media print { + /* line 8, ../sass/bootstrap/_print.scss */ + * { + text-shadow: none !important; + color: #000 !important; + background: transparent !important; + box-shadow: none !important; + } + + /* line 15, ../sass/bootstrap/_print.scss */ + a, + a:visited { + text-decoration: underline; + } + + /* line 20, ../sass/bootstrap/_print.scss */ + a[href]:after { + content: " (" attr(href) ")"; + } + + /* line 24, ../sass/bootstrap/_print.scss */ + abbr[title]:after { + content: " (" attr(title) ")"; + } + + /* line 29, ../sass/bootstrap/_print.scss */ + a[href^="javascript:"]:after, + a[href^="#"]:after { + content: ""; + } + + /* line 34, ../sass/bootstrap/_print.scss */ + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + + /* line 40, ../sass/bootstrap/_print.scss */ + thead { + display: table-header-group; + } + + /* line 44, ../sass/bootstrap/_print.scss */ + tr, + img { + page-break-inside: avoid; + } + + /* line 49, ../sass/bootstrap/_print.scss */ + img { + max-width: 100% !important; + } + + /* line 53, ../sass/bootstrap/_print.scss */ + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + + /* line 60, ../sass/bootstrap/_print.scss */ + h2, + h3 { + page-break-after: avoid; + } + + /* line 67, ../sass/bootstrap/_print.scss */ + select { + background: #fff !important; + } + + /* line 72, ../sass/bootstrap/_print.scss */ + .navbar { + display: none; + } + + /* line 76, ../sass/bootstrap/_print.scss */ + .table td, + .table th { + background-color: #fff !important; + } + + /* line 83, ../sass/bootstrap/_print.scss */ + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + + /* line 87, ../sass/bootstrap/_print.scss */ + .label { + border: 1px solid #000; + } + + /* line 91, ../sass/bootstrap/_print.scss */ + .table { + border-collapse: collapse !important; + } + + /* line 95, ../sass/bootstrap/_print.scss */ + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} +@font-face { + font-family: 'Glyphicons Halflings'; + src: url("bootstrap/glyphicons-halflings-regular.eot"); + src: url("bootstrap/glyphicons-halflings-regular.eot?#iefix") format("embedded-opentype"), url("bootstrap/glyphicons-halflings-regular.woff") format("woff"), url("bootstrap/glyphicons-halflings-regular.ttf") format("truetype"), url("bootstrap/glyphicons-halflings-regular.svg#glyphicons_halflingsregular") format("svg"); +} +/* line 25, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* line 38, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-asterisk:before { + content: "\2a"; +} + +/* line 39, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-plus:before { + content: "\2b"; +} + +/* line 40, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-euro:before { + content: "\20ac"; +} + +/* line 41, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-minus:before { + content: "\2212"; +} + +/* line 42, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-cloud:before { + content: "\2601"; +} + +/* line 43, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-envelope:before { + content: "\2709"; +} + +/* line 44, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-pencil:before { + content: "\270f"; +} + +/* line 45, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-glass:before { + content: "\e001"; +} + +/* line 46, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-music:before { + content: "\e002"; +} + +/* line 47, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-search:before { + content: "\e003"; +} + +/* line 48, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-heart:before { + content: "\e005"; +} + +/* line 49, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-star:before { + content: "\e006"; +} + +/* line 50, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-star-empty:before { + content: "\e007"; +} + +/* line 51, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-user:before { + content: "\e008"; +} + +/* line 52, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-film:before { + content: "\e009"; +} + +/* line 53, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-th-large:before { + content: "\e010"; +} + +/* line 54, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-th:before { + content: "\e011"; +} + +/* line 55, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-th-list:before { + content: "\e012"; +} + +/* line 56, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-ok:before { + content: "\e013"; +} + +/* line 57, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-remove:before { + content: "\e014"; +} + +/* line 58, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-zoom-in:before { + content: "\e015"; +} + +/* line 59, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-zoom-out:before { + content: "\e016"; +} + +/* line 60, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-off:before { + content: "\e017"; +} + +/* line 61, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-signal:before { + content: "\e018"; +} + +/* line 62, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-cog:before { + content: "\e019"; +} + +/* line 63, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-trash:before { + content: "\e020"; +} + +/* line 64, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-home:before { + content: "\e021"; +} + +/* line 65, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-file:before { + content: "\e022"; +} + +/* line 66, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-time:before { + content: "\e023"; +} + +/* line 67, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-road:before { + content: "\e024"; +} + +/* line 68, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-download-alt:before { + content: "\e025"; +} + +/* line 69, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-download:before { + content: "\e026"; +} + +/* line 70, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-upload:before { + content: "\e027"; +} + +/* line 71, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-inbox:before { + content: "\e028"; +} + +/* line 72, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-play-circle:before { + content: "\e029"; +} + +/* line 73, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-repeat:before { + content: "\e030"; +} + +/* line 74, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-refresh:before { + content: "\e031"; +} + +/* line 75, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-list-alt:before { + content: "\e032"; +} + +/* line 76, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-lock:before { + content: "\e033"; +} + +/* line 77, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-flag:before { + content: "\e034"; +} + +/* line 78, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-headphones:before { + content: "\e035"; +} + +/* line 79, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-volume-off:before { + content: "\e036"; +} + +/* line 80, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-volume-down:before { + content: "\e037"; +} + +/* line 81, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-volume-up:before { + content: "\e038"; +} + +/* line 82, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-qrcode:before { + content: "\e039"; +} + +/* line 83, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-barcode:before { + content: "\e040"; +} + +/* line 84, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-tag:before { + content: "\e041"; +} + +/* line 85, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-tags:before { + content: "\e042"; +} + +/* line 86, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-book:before { + content: "\e043"; +} + +/* line 87, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-bookmark:before { + content: "\e044"; +} + +/* line 88, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-print:before { + content: "\e045"; +} + +/* line 89, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-camera:before { + content: "\e046"; +} + +/* line 90, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-font:before { + content: "\e047"; +} + +/* line 91, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-bold:before { + content: "\e048"; +} + +/* line 92, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-italic:before { + content: "\e049"; +} + +/* line 93, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-text-height:before { + content: "\e050"; +} + +/* line 94, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-text-width:before { + content: "\e051"; +} + +/* line 95, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-align-left:before { + content: "\e052"; +} + +/* line 96, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-align-center:before { + content: "\e053"; +} + +/* line 97, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-align-right:before { + content: "\e054"; +} + +/* line 98, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-align-justify:before { + content: "\e055"; +} + +/* line 99, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-list:before { + content: "\e056"; +} + +/* line 100, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-indent-left:before { + content: "\e057"; +} + +/* line 101, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-indent-right:before { + content: "\e058"; +} + +/* line 102, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-facetime-video:before { + content: "\e059"; +} + +/* line 103, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-picture:before { + content: "\e060"; +} + +/* line 104, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-map-marker:before { + content: "\e062"; +} + +/* line 105, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-adjust:before { + content: "\e063"; +} + +/* line 106, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-tint:before { + content: "\e064"; +} + +/* line 107, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-edit:before { + content: "\e065"; +} + +/* line 108, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-share:before { + content: "\e066"; +} + +/* line 109, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-check:before { + content: "\e067"; +} + +/* line 110, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-move:before { + content: "\e068"; +} + +/* line 111, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-step-backward:before { + content: "\e069"; +} + +/* line 112, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-fast-backward:before { + content: "\e070"; +} + +/* line 113, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-backward:before { + content: "\e071"; +} + +/* line 114, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-play:before { + content: "\e072"; +} + +/* line 115, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-pause:before { + content: "\e073"; +} + +/* line 116, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-stop:before { + content: "\e074"; +} + +/* line 117, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-forward:before { + content: "\e075"; +} + +/* line 118, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-fast-forward:before { + content: "\e076"; +} + +/* line 119, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-step-forward:before { + content: "\e077"; +} + +/* line 120, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-eject:before { + content: "\e078"; +} + +/* line 121, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-chevron-left:before { + content: "\e079"; +} + +/* line 122, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-chevron-right:before { + content: "\e080"; +} + +/* line 123, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-plus-sign:before { + content: "\e081"; +} + +/* line 124, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-minus-sign:before { + content: "\e082"; +} + +/* line 125, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-remove-sign:before { + content: "\e083"; +} + +/* line 126, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-ok-sign:before { + content: "\e084"; +} + +/* line 127, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-question-sign:before { + content: "\e085"; +} + +/* line 128, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-info-sign:before { + content: "\e086"; +} + +/* line 129, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-screenshot:before { + content: "\e087"; +} + +/* line 130, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-remove-circle:before { + content: "\e088"; +} + +/* line 131, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-ok-circle:before { + content: "\e089"; +} + +/* line 132, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-ban-circle:before { + content: "\e090"; +} + +/* line 133, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-arrow-left:before { + content: "\e091"; +} + +/* line 134, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-arrow-right:before { + content: "\e092"; +} + +/* line 135, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-arrow-up:before { + content: "\e093"; +} + +/* line 136, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-arrow-down:before { + content: "\e094"; +} + +/* line 137, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-share-alt:before { + content: "\e095"; +} + +/* line 138, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-resize-full:before { + content: "\e096"; +} + +/* line 139, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-resize-small:before { + content: "\e097"; +} + +/* line 140, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-exclamation-sign:before { + content: "\e101"; +} + +/* line 141, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-gift:before { + content: "\e102"; +} + +/* line 142, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-leaf:before { + content: "\e103"; +} + +/* line 143, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-fire:before { + content: "\e104"; +} + +/* line 144, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-eye-open:before { + content: "\e105"; +} + +/* line 145, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-eye-close:before { + content: "\e106"; +} + +/* line 146, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-warning-sign:before { + content: "\e107"; +} + +/* line 147, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-plane:before { + content: "\e108"; +} + +/* line 148, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-calendar:before { + content: "\e109"; +} + +/* line 149, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-random:before { + content: "\e110"; +} + +/* line 150, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-comment:before { + content: "\e111"; +} + +/* line 151, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-magnet:before { + content: "\e112"; +} + +/* line 152, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-chevron-up:before { + content: "\e113"; +} + +/* line 153, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-chevron-down:before { + content: "\e114"; +} + +/* line 154, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-retweet:before { + content: "\e115"; +} + +/* line 155, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-shopping-cart:before { + content: "\e116"; +} + +/* line 156, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-folder-close:before { + content: "\e117"; +} + +/* line 157, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-folder-open:before { + content: "\e118"; +} + +/* line 158, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-resize-vertical:before { + content: "\e119"; +} + +/* line 159, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-resize-horizontal:before { + content: "\e120"; +} + +/* line 160, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-hdd:before { + content: "\e121"; +} + +/* line 161, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-bullhorn:before { + content: "\e122"; +} + +/* line 162, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-bell:before { + content: "\e123"; +} + +/* line 163, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-certificate:before { + content: "\e124"; +} + +/* line 164, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-thumbs-up:before { + content: "\e125"; +} + +/* line 165, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-thumbs-down:before { + content: "\e126"; +} + +/* line 166, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-hand-right:before { + content: "\e127"; +} + +/* line 167, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-hand-left:before { + content: "\e128"; +} + +/* line 168, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-hand-up:before { + content: "\e129"; +} + +/* line 169, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-hand-down:before { + content: "\e130"; +} + +/* line 170, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} + +/* line 171, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} + +/* line 172, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} + +/* line 173, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} + +/* line 174, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-globe:before { + content: "\e135"; +} + +/* line 175, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-wrench:before { + content: "\e136"; +} + +/* line 176, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-tasks:before { + content: "\e137"; +} + +/* line 177, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-filter:before { + content: "\e138"; +} + +/* line 178, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-briefcase:before { + content: "\e139"; +} + +/* line 179, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-fullscreen:before { + content: "\e140"; +} + +/* line 180, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-dashboard:before { + content: "\e141"; +} + +/* line 181, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-paperclip:before { + content: "\e142"; +} + +/* line 182, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-heart-empty:before { + content: "\e143"; +} + +/* line 183, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-link:before { + content: "\e144"; +} + +/* line 184, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-phone:before { + content: "\e145"; +} + +/* line 185, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-pushpin:before { + content: "\e146"; +} + +/* line 186, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-usd:before { + content: "\e148"; +} + +/* line 187, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-gbp:before { + content: "\e149"; +} + +/* line 188, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-sort:before { + content: "\e150"; +} + +/* line 189, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} + +/* line 190, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} + +/* line 191, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-sort-by-order:before { + content: "\e153"; +} + +/* line 192, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} + +/* line 193, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} + +/* line 194, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} + +/* line 195, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-unchecked:before { + content: "\e157"; +} + +/* line 196, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-expand:before { + content: "\e158"; +} + +/* line 197, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-collapse-down:before { + content: "\e159"; +} + +/* line 198, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-collapse-up:before { + content: "\e160"; +} + +/* line 199, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-log-in:before { + content: "\e161"; +} + +/* line 200, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-flash:before { + content: "\e162"; +} + +/* line 201, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-log-out:before { + content: "\e163"; +} + +/* line 202, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-new-window:before { + content: "\e164"; +} + +/* line 203, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-record:before { + content: "\e165"; +} + +/* line 204, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-save:before { + content: "\e166"; +} + +/* line 205, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-open:before { + content: "\e167"; +} + +/* line 206, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-saved:before { + content: "\e168"; +} + +/* line 207, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-import:before { + content: "\e169"; +} + +/* line 208, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-export:before { + content: "\e170"; +} + +/* line 209, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-send:before { + content: "\e171"; +} + +/* line 210, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-floppy-disk:before { + content: "\e172"; +} + +/* line 211, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-floppy-saved:before { + content: "\e173"; +} + +/* line 212, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-floppy-remove:before { + content: "\e174"; +} + +/* line 213, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-floppy-save:before { + content: "\e175"; +} + +/* line 214, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-floppy-open:before { + content: "\e176"; +} + +/* line 215, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-credit-card:before { + content: "\e177"; +} + +/* line 216, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-transfer:before { + content: "\e178"; +} + +/* line 217, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-cutlery:before { + content: "\e179"; +} + +/* line 218, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-header:before { + content: "\e180"; +} + +/* line 219, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-compressed:before { + content: "\e181"; +} + +/* line 220, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-earphone:before { + content: "\e182"; +} + +/* line 221, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-phone-alt:before { + content: "\e183"; +} + +/* line 222, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-tower:before { + content: "\e184"; +} + +/* line 223, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-stats:before { + content: "\e185"; +} + +/* line 224, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-sd-video:before { + content: "\e186"; +} + +/* line 225, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-hd-video:before { + content: "\e187"; +} + +/* line 226, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-subtitles:before { + content: "\e188"; +} + +/* line 227, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-sound-stereo:before { + content: "\e189"; +} + +/* line 228, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-sound-dolby:before { + content: "\e190"; +} + +/* line 229, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-sound-5-1:before { + content: "\e191"; +} + +/* line 230, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-sound-6-1:before { + content: "\e192"; +} + +/* line 231, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-sound-7-1:before { + content: "\e193"; +} + +/* line 232, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-copyright-mark:before { + content: "\e194"; +} + +/* line 233, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-registration-mark:before { + content: "\e195"; +} + +/* line 234, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-cloud-download:before { + content: "\e197"; +} + +/* line 235, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-cloud-upload:before { + content: "\e198"; +} + +/* line 236, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-tree-conifer:before { + content: "\e199"; +} + +/* line 237, ../sass/bootstrap/_glyphicons.scss */ +.glyphicon-tree-deciduous:before { + content: "\e200"; +} + +/* line 11, ../sass/bootstrap/_scaffolding.scss */ +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +/* line 14, ../sass/bootstrap/_scaffolding.scss */ +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +/* line 22, ../sass/bootstrap/_scaffolding.scss */ +html { + font-size: 10px; + -webkit-tap-highlight-color: transparent; +} + +/* line 27, ../sass/bootstrap/_scaffolding.scss */ +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857; + color: #333333; + background-color: #fff; +} + +/* line 36, ../sass/bootstrap/_scaffolding.scss */ +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} + +/* line 48, ../sass/bootstrap/_scaffolding.scss */ +a { + color: #428bca; + text-decoration: none; +} +/* line 52, ../sass/bootstrap/_scaffolding.scss */ +a:hover, a:focus { + color: #2a6496; + text-decoration: underline; +} +/* line 58, ../sass/bootstrap/_scaffolding.scss */ +a:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +/* line 69, ../sass/bootstrap/_scaffolding.scss */ +figure { + margin: 0; +} + +/* line 76, ../sass/bootstrap/_scaffolding.scss */ +img { + vertical-align: middle; +} + +/* line 81, ../sass/bootstrap/_scaffolding.scss */ +.img-responsive { + display: block; + width: 100% \9; + max-width: 100%; + height: auto; +} + +/* line 86, ../sass/bootstrap/_scaffolding.scss */ +.img-rounded { + border-radius: 6px; +} + +/* line 93, ../sass/bootstrap/_scaffolding.scss */ +.img-thumbnail { + padding: 4px; + line-height: 1.42857; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + display: inline-block; + width: 100% \9; + max-width: 100%; + height: auto; +} + +/* line 106, ../sass/bootstrap/_scaffolding.scss */ +.img-circle { + border-radius: 50%; +} + +/* line 113, ../sass/bootstrap/_scaffolding.scss */ +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eeeeee; +} + +/* line 125, ../sass/bootstrap/_scaffolding.scss */ +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} + +/* line 141, ../sass/bootstrap/_scaffolding.scss */ +.sr-only-focusable:active, .sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} + +/* line 9, ../sass/bootstrap/_type.scss */ +h1, h2, h3, h4, h5, h6, +.h1, .h2, .h3, .h4, .h5, .h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; +} +/* line 16, ../sass/bootstrap/_type.scss */ +h1 small, +h1 .small, h2 small, +h2 .small, h3 small, +h3 .small, h4 small, +h4 .small, h5 small, +h5 .small, h6 small, +h6 .small, +.h1 small, +.h1 .small, .h2 small, +.h2 .small, .h3 small, +.h3 .small, .h4 small, +.h4 .small, .h5 small, +.h5 .small, .h6 small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #777777; +} + +/* line 24, ../sass/bootstrap/_type.scss */ +h1, .h1, +h2, .h2, +h3, .h3 { + margin-top: 20px; + margin-bottom: 10px; +} +/* line 30, ../sass/bootstrap/_type.scss */ +h1 small, +h1 .small, .h1 small, +.h1 .small, +h2 small, +h2 .small, .h2 small, +.h2 .small, +h3 small, +h3 .small, .h3 small, +.h3 .small { + font-size: 65%; +} + +/* line 35, ../sass/bootstrap/_type.scss */ +h4, .h4, +h5, .h5, +h6, .h6 { + margin-top: 10px; + margin-bottom: 10px; +} +/* line 41, ../sass/bootstrap/_type.scss */ +h4 small, +h4 .small, .h4 small, +.h4 .small, +h5 small, +h5 .small, .h5 small, +.h5 .small, +h6 small, +h6 .small, .h6 small, +.h6 .small { + font-size: 75%; +} + +/* line 47, ../sass/bootstrap/_type.scss */ +h1, .h1 { + font-size: 36px; +} + +/* line 48, ../sass/bootstrap/_type.scss */ +h2, .h2 { + font-size: 30px; +} + +/* line 49, ../sass/bootstrap/_type.scss */ +h3, .h3 { + font-size: 24px; +} + +/* line 50, ../sass/bootstrap/_type.scss */ +h4, .h4 { + font-size: 18px; +} + +/* line 51, ../sass/bootstrap/_type.scss */ +h5, .h5 { + font-size: 14px; +} + +/* line 52, ../sass/bootstrap/_type.scss */ +h6, .h6 { + font-size: 12px; +} + +/* line 58, ../sass/bootstrap/_type.scss */ +p { + margin: 0 0 10px; +} + +/* line 62, ../sass/bootstrap/_type.scss */ +.lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 300; + line-height: 1.4; +} +@media (min-width: 768px) { + /* line 62, ../sass/bootstrap/_type.scss */ + .lead { + font-size: 21px; + } +} + +/* line 78, ../sass/bootstrap/_type.scss */ +small, +.small { + font-size: 85%; +} + +/* line 84, ../sass/bootstrap/_type.scss */ +cite { + font-style: normal; +} + +/* line 88, ../sass/bootstrap/_type.scss */ +mark, +.mark { + background-color: #fcf8e3; + padding: .2em; +} + +/* line 95, ../sass/bootstrap/_type.scss */ +.text-left { + text-align: left; +} + +/* line 96, ../sass/bootstrap/_type.scss */ +.text-right { + text-align: right; +} + +/* line 97, ../sass/bootstrap/_type.scss */ +.text-center { + text-align: center; +} + +/* line 98, ../sass/bootstrap/_type.scss */ +.text-justify { + text-align: justify; +} + +/* line 99, ../sass/bootstrap/_type.scss */ +.text-nowrap { + white-space: nowrap; +} + +/* line 102, ../sass/bootstrap/_type.scss */ +.text-lowercase { + text-transform: lowercase; +} + +/* line 103, ../sass/bootstrap/_type.scss */ +.text-uppercase { + text-transform: uppercase; +} + +/* line 104, ../sass/bootstrap/_type.scss */ +.text-capitalize { + text-transform: capitalize; +} + +/* line 107, ../sass/bootstrap/_type.scss */ +.text-muted { + color: #777777; +} + +/* line 5, ../sass/bootstrap/mixins/_text-emphasis.scss */ +.text-primary { + color: #428bca; +} + +/* line 8, ../sass/bootstrap/mixins/_text-emphasis.scss */ +a.text-primary:hover { + color: #3071a9; +} + +/* line 5, ../sass/bootstrap/mixins/_text-emphasis.scss */ +.text-success { + color: #3c763d; +} + +/* line 8, ../sass/bootstrap/mixins/_text-emphasis.scss */ +a.text-success:hover { + color: #2b542c; +} + +/* line 5, ../sass/bootstrap/mixins/_text-emphasis.scss */ +.text-info { + color: #31708f; +} + +/* line 8, ../sass/bootstrap/mixins/_text-emphasis.scss */ +a.text-info:hover { + color: #245269; +} + +/* line 5, ../sass/bootstrap/mixins/_text-emphasis.scss */ +.text-warning { + color: #8a6d3b; +} + +/* line 8, ../sass/bootstrap/mixins/_text-emphasis.scss */ +a.text-warning:hover { + color: #66512c; +} + +/* line 5, ../sass/bootstrap/mixins/_text-emphasis.scss */ +.text-danger { + color: #a94442; +} + +/* line 8, ../sass/bootstrap/mixins/_text-emphasis.scss */ +a.text-danger:hover { + color: #843534; +} + +/* line 124, ../sass/bootstrap/_type.scss */ +.bg-primary { + color: #fff; +} + +/* line 5, ../sass/bootstrap/mixins/_background-variant.scss */ +.bg-primary { + background-color: #428bca; +} + +/* line 8, ../sass/bootstrap/mixins/_background-variant.scss */ +a.bg-primary:hover { + background-color: #3071a9; +} + +/* line 5, ../sass/bootstrap/mixins/_background-variant.scss */ +.bg-success { + background-color: #dff0d8; +} + +/* line 8, ../sass/bootstrap/mixins/_background-variant.scss */ +a.bg-success:hover { + background-color: #c1e2b3; +} + +/* line 5, ../sass/bootstrap/mixins/_background-variant.scss */ +.bg-info { + background-color: #d9edf7; +} + +/* line 8, ../sass/bootstrap/mixins/_background-variant.scss */ +a.bg-info:hover { + background-color: #afd9ee; +} + +/* line 5, ../sass/bootstrap/mixins/_background-variant.scss */ +.bg-warning { + background-color: #fcf8e3; +} + +/* line 8, ../sass/bootstrap/mixins/_background-variant.scss */ +a.bg-warning:hover { + background-color: #f7ecb5; +} + +/* line 5, ../sass/bootstrap/mixins/_background-variant.scss */ +.bg-danger { + background-color: #f2dede; +} + +/* line 8, ../sass/bootstrap/mixins/_background-variant.scss */ +a.bg-danger:hover { + background-color: #e4b9b9; +} + +/* line 143, ../sass/bootstrap/_type.scss */ +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eeeeee; +} + +/* line 154, ../sass/bootstrap/_type.scss */ +ul, +ol { + margin-top: 0; + margin-bottom: 10px; +} +/* line 158, ../sass/bootstrap/_type.scss */ +ul ul, +ul ol, +ol ul, +ol ol { + margin-bottom: 0; +} + +/* line 167, ../sass/bootstrap/_type.scss */ +.list-unstyled, .list-inline { + padding-left: 0; + list-style: none; +} + +/* line 173, ../sass/bootstrap/_type.scss */ +.list-inline { + margin-left: -5px; +} +/* line 177, ../sass/bootstrap/_type.scss */ +.list-inline > li { + display: inline-block; + padding-left: 5px; + padding-right: 5px; +} + +/* line 185, ../sass/bootstrap/_type.scss */ +dl { + margin-top: 0; + margin-bottom: 20px; +} + +/* line 189, ../sass/bootstrap/_type.scss */ +dt, +dd { + line-height: 1.42857; +} + +/* line 193, ../sass/bootstrap/_type.scss */ +dt { + font-weight: bold; +} + +/* line 196, ../sass/bootstrap/_type.scss */ +dd { + margin-left: 0; +} + +/* line 14, ../sass/bootstrap/mixins/_clearfix.scss */ +.dl-horizontal dd:before, .dl-horizontal dd:after { + content: " "; + display: table; +} +/* line 19, ../sass/bootstrap/mixins/_clearfix.scss */ +.dl-horizontal dd:after { + clear: both; +} +@media (min-width: 768px) { + /* line 211, ../sass/bootstrap/_type.scss */ + .dl-horizontal dt { + float: left; + width: 160px; + clear: left; + text-align: right; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + /* line 218, ../sass/bootstrap/_type.scss */ + .dl-horizontal dd { + margin-left: 180px; + } +} + +/* line 229, ../sass/bootstrap/_type.scss */ +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #777777; +} + +/* line 235, ../sass/bootstrap/_type.scss */ +.initialism { + font-size: 90%; + text-transform: uppercase; +} + +/* line 241, ../sass/bootstrap/_type.scss */ +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eeeeee; +} +/* line 250, ../sass/bootstrap/_type.scss */ +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +/* line 257, ../sass/bootstrap/_type.scss */ +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857; + color: #777777; +} +/* line 265, ../sass/bootstrap/_type.scss */ +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: '\2014 \00A0'; +} + +/* line 274, ../sass/bootstrap/_type.scss */ +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #eeeeee; + border-left: 0; + text-align: right; +} +/* line 286, ../sass/bootstrap/_type.scss */ +.blockquote-reverse footer:before, +.blockquote-reverse small:before, +.blockquote-reverse .small:before, +blockquote.pull-right footer:before, +blockquote.pull-right small:before, +blockquote.pull-right .small:before { + content: ''; +} +/* line 287, ../sass/bootstrap/_type.scss */ +.blockquote-reverse footer:after, +.blockquote-reverse small:after, +.blockquote-reverse .small:after, +blockquote.pull-right footer:after, +blockquote.pull-right small:after, +blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} + +/* line 294, ../sass/bootstrap/_type.scss */ +blockquote:before, +blockquote:after { + content: ""; +} + +/* line 300, ../sass/bootstrap/_type.scss */ +address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857; +} + +/* line 7, ../sass/bootstrap/_code.scss */ +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} + +/* line 15, ../sass/bootstrap/_code.scss */ +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + border-radius: 4px; +} + +/* line 24, ../sass/bootstrap/_code.scss */ +kbd { + padding: 2px 4px; + font-size: 90%; + color: #fff; + background-color: #333; + border-radius: 3px; + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); +} +/* line 32, ../sass/bootstrap/_code.scss */ +kbd kbd { + padding: 0; + font-size: 100%; + box-shadow: none; +} + +/* line 40, ../sass/bootstrap/_code.scss */ +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857; + word-break: break-all; + word-wrap: break-word; + color: #333333; + background-color: #f5f5f5; + border: 1px solid #ccc; + border-radius: 4px; +} +/* line 54, ../sass/bootstrap/_code.scss */ +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} + +/* line 65, ../sass/bootstrap/_code.scss */ +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} + +/* line 10, ../sass/bootstrap/_grid.scss */ +.container { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +/* line 14, ../sass/bootstrap/mixins/_clearfix.scss */ +.container:before, .container:after { + content: " "; + display: table; +} +/* line 19, ../sass/bootstrap/mixins/_clearfix.scss */ +.container:after { + clear: both; +} +@media (min-width: 768px) { + /* line 10, ../sass/bootstrap/_grid.scss */ + .container { + width: 750px; + } +} +@media (min-width: 992px) { + /* line 10, ../sass/bootstrap/_grid.scss */ + .container { + width: 970px; + } +} +@media (min-width: 1200px) { + /* line 10, ../sass/bootstrap/_grid.scss */ + .container { + width: 1170px; + } +} + +/* line 30, ../sass/bootstrap/_grid.scss */ +.container-fluid { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +/* line 14, ../sass/bootstrap/mixins/_clearfix.scss */ +.container-fluid:before, .container-fluid:after { + content: " "; + display: table; +} +/* line 19, ../sass/bootstrap/mixins/_clearfix.scss */ +.container-fluid:after { + clear: both; +} + +/* line 39, ../sass/bootstrap/_grid.scss */ +.row { + margin-left: -15px; + margin-right: -15px; +} +/* line 14, ../sass/bootstrap/mixins/_clearfix.scss */ +.row:before, .row:after { + content: " "; + display: table; +} +/* line 19, ../sass/bootstrap/mixins/_clearfix.scss */ +.row:after { + clear: both; +} + +/* line 11, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-left: 15px; + padding-right: 15px; +} + +/* line 27, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} + +/* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-1 { + width: 8.33333%; +} + +/* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-2 { + width: 16.66667%; +} + +/* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-3 { + width: 25%; +} + +/* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-4 { + width: 33.33333%; +} + +/* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-5 { + width: 41.66667%; +} + +/* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-6 { + width: 50%; +} + +/* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-7 { + width: 58.33333%; +} + +/* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-8 { + width: 66.66667%; +} + +/* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-9 { + width: 75%; +} + +/* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-10 { + width: 83.33333%; +} + +/* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-11 { + width: 91.66667%; +} + +/* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-12 { + width: 100%; +} + +/* line 55, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-pull-0 { + right: auto; +} + +/* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-pull-1 { + right: 8.33333%; +} + +/* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-pull-2 { + right: 16.66667%; +} + +/* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-pull-3 { + right: 25%; +} + +/* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-pull-4 { + right: 33.33333%; +} + +/* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-pull-5 { + right: 41.66667%; +} + +/* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-pull-6 { + right: 50%; +} + +/* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-pull-7 { + right: 58.33333%; +} + +/* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-pull-8 { + right: 66.66667%; +} + +/* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-pull-9 { + right: 75%; +} + +/* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-pull-10 { + right: 83.33333%; +} + +/* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-pull-11 { + right: 91.66667%; +} + +/* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-pull-12 { + right: 100%; +} + +/* line 45, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-push-0 { + left: auto; +} + +/* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-push-1 { + left: 8.33333%; +} + +/* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-push-2 { + left: 16.66667%; +} + +/* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-push-3 { + left: 25%; +} + +/* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-push-4 { + left: 33.33333%; +} + +/* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-push-5 { + left: 41.66667%; +} + +/* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-push-6 { + left: 50%; +} + +/* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-push-7 { + left: 58.33333%; +} + +/* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-push-8 { + left: 66.66667%; +} + +/* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-push-9 { + left: 75%; +} + +/* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-push-10 { + left: 83.33333%; +} + +/* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-push-11 { + left: 91.66667%; +} + +/* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-push-12 { + left: 100%; +} + +/* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-offset-0 { + margin-left: 0%; +} + +/* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-offset-1 { + margin-left: 8.33333%; +} + +/* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-offset-2 { + margin-left: 16.66667%; +} + +/* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-offset-3 { + margin-left: 25%; +} + +/* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-offset-4 { + margin-left: 33.33333%; +} + +/* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-offset-5 { + margin-left: 41.66667%; +} + +/* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-offset-6 { + margin-left: 50%; +} + +/* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-offset-7 { + margin-left: 58.33333%; +} + +/* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-offset-8 { + margin-left: 66.66667%; +} + +/* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-offset-9 { + margin-left: 75%; +} + +/* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-offset-10 { + margin-left: 83.33333%; +} + +/* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-offset-11 { + margin-left: 91.66667%; +} + +/* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ +.col-xs-offset-12 { + margin-left: 100%; +} + +@media (min-width: 768px) { + /* line 27, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-1 { + width: 8.33333%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-2 { + width: 16.66667%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-3 { + width: 25%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-4 { + width: 33.33333%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-5 { + width: 41.66667%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-6 { + width: 50%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-7 { + width: 58.33333%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-8 { + width: 66.66667%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-9 { + width: 75%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-10 { + width: 83.33333%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-11 { + width: 91.66667%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-12 { + width: 100%; + } + + /* line 55, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-pull-0 { + right: auto; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-pull-1 { + right: 8.33333%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-pull-2 { + right: 16.66667%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-pull-3 { + right: 25%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-pull-4 { + right: 33.33333%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-pull-5 { + right: 41.66667%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-pull-6 { + right: 50%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-pull-7 { + right: 58.33333%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-pull-8 { + right: 66.66667%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-pull-9 { + right: 75%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-pull-10 { + right: 83.33333%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-pull-11 { + right: 91.66667%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-pull-12 { + right: 100%; + } + + /* line 45, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-push-0 { + left: auto; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-push-1 { + left: 8.33333%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-push-2 { + left: 16.66667%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-push-3 { + left: 25%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-push-4 { + left: 33.33333%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-push-5 { + left: 41.66667%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-push-6 { + left: 50%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-push-7 { + left: 58.33333%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-push-8 { + left: 66.66667%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-push-9 { + left: 75%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-push-10 { + left: 83.33333%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-push-11 { + left: 91.66667%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-push-12 { + left: 100%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-offset-0 { + margin-left: 0%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-offset-1 { + margin-left: 8.33333%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-offset-2 { + margin-left: 16.66667%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-offset-3 { + margin-left: 25%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-offset-4 { + margin-left: 33.33333%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-offset-5 { + margin-left: 41.66667%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-offset-6 { + margin-left: 50%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-offset-7 { + margin-left: 58.33333%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-offset-8 { + margin-left: 66.66667%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-offset-9 { + margin-left: 75%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-offset-10 { + margin-left: 83.33333%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-offset-11 { + margin-left: 91.66667%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-sm-offset-12 { + margin-left: 100%; + } +} +@media (min-width: 992px) { + /* line 27, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-1 { + width: 8.33333%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-2 { + width: 16.66667%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-3 { + width: 25%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-4 { + width: 33.33333%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-5 { + width: 41.66667%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-6 { + width: 50%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-7 { + width: 58.33333%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-8 { + width: 66.66667%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-9 { + width: 75%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-10 { + width: 83.33333%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-11 { + width: 91.66667%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-12 { + width: 100%; + } + + /* line 55, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-pull-0 { + right: auto; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-pull-1 { + right: 8.33333%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-pull-2 { + right: 16.66667%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-pull-3 { + right: 25%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-pull-4 { + right: 33.33333%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-pull-5 { + right: 41.66667%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-pull-6 { + right: 50%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-pull-7 { + right: 58.33333%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-pull-8 { + right: 66.66667%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-pull-9 { + right: 75%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-pull-10 { + right: 83.33333%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-pull-11 { + right: 91.66667%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-pull-12 { + right: 100%; + } + + /* line 45, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-push-0 { + left: auto; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-push-1 { + left: 8.33333%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-push-2 { + left: 16.66667%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-push-3 { + left: 25%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-push-4 { + left: 33.33333%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-push-5 { + left: 41.66667%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-push-6 { + left: 50%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-push-7 { + left: 58.33333%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-push-8 { + left: 66.66667%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-push-9 { + left: 75%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-push-10 { + left: 83.33333%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-push-11 { + left: 91.66667%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-push-12 { + left: 100%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-offset-0 { + margin-left: 0%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-offset-1 { + margin-left: 8.33333%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-offset-2 { + margin-left: 16.66667%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-offset-3 { + margin-left: 25%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-offset-4 { + margin-left: 33.33333%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-offset-5 { + margin-left: 41.66667%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-offset-6 { + margin-left: 50%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-offset-7 { + margin-left: 58.33333%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-offset-8 { + margin-left: 66.66667%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-offset-9 { + margin-left: 75%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-offset-10 { + margin-left: 83.33333%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-offset-11 { + margin-left: 91.66667%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-md-offset-12 { + margin-left: 100%; + } +} +@media (min-width: 1200px) { + /* line 27, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-1 { + width: 8.33333%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-2 { + width: 16.66667%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-3 { + width: 25%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-4 { + width: 33.33333%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-5 { + width: 41.66667%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-6 { + width: 50%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-7 { + width: 58.33333%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-8 { + width: 66.66667%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-9 { + width: 75%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-10 { + width: 83.33333%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-11 { + width: 91.66667%; + } + + /* line 35, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-12 { + width: 100%; + } + + /* line 55, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-pull-0 { + right: auto; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-pull-1 { + right: 8.33333%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-pull-2 { + right: 16.66667%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-pull-3 { + right: 25%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-pull-4 { + right: 33.33333%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-pull-5 { + right: 41.66667%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-pull-6 { + right: 50%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-pull-7 { + right: 58.33333%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-pull-8 { + right: 66.66667%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-pull-9 { + right: 75%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-pull-10 { + right: 83.33333%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-pull-11 { + right: 91.66667%; + } + + /* line 50, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-pull-12 { + right: 100%; + } + + /* line 45, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-push-0 { + left: auto; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-push-1 { + left: 8.33333%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-push-2 { + left: 16.66667%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-push-3 { + left: 25%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-push-4 { + left: 33.33333%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-push-5 { + left: 41.66667%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-push-6 { + left: 50%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-push-7 { + left: 58.33333%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-push-8 { + left: 66.66667%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-push-9 { + left: 75%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-push-10 { + left: 83.33333%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-push-11 { + left: 91.66667%; + } + + /* line 40, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-push-12 { + left: 100%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-offset-0 { + margin-left: 0%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-offset-1 { + margin-left: 8.33333%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-offset-2 { + margin-left: 16.66667%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-offset-3 { + margin-left: 25%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-offset-4 { + margin-left: 33.33333%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-offset-5 { + margin-left: 41.66667%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-offset-6 { + margin-left: 50%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-offset-7 { + margin-left: 58.33333%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-offset-8 { + margin-left: 66.66667%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-offset-9 { + margin-left: 75%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-offset-10 { + margin-left: 83.33333%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-offset-11 { + margin-left: 91.66667%; + } + + /* line 60, ../sass/bootstrap/mixins/_grid-framework.scss */ + .col-lg-offset-12 { + margin-left: 100%; + } +} +/* line 6, ../sass/bootstrap/_tables.scss */ +table { + background-color: transparent; +} + +/* line 9, ../sass/bootstrap/_tables.scss */ +th { + text-align: left; +} + +/* line 16, ../sass/bootstrap/_tables.scss */ +.table { + width: 100%; + max-width: 100%; + margin-bottom: 20px; +} +/* line 25, ../sass/bootstrap/_tables.scss */ +.table > thead > tr > th, +.table > thead > tr > td, +.table > tbody > tr > th, +.table > tbody > tr > td, +.table > tfoot > tr > th, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.42857; + vertical-align: top; + border-top: 1px solid #ddd; +} +/* line 35, ../sass/bootstrap/_tables.scss */ +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #ddd; +} +/* line 44, ../sass/bootstrap/_tables.scss */ +.table > caption + thead > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > td, +.table > thead:first-child > tr:first-child > th, +.table > thead:first-child > tr:first-child > td { + border-top: 0; +} +/* line 51, ../sass/bootstrap/_tables.scss */ +.table > tbody + tbody { + border-top: 2px solid #ddd; +} +/* line 56, ../sass/bootstrap/_tables.scss */ +.table .table { + background-color: #fff; +} + +/* line 69, ../sass/bootstrap/_tables.scss */ +.table-condensed > thead > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > th, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > th, +.table-condensed > tfoot > tr > td { + padding: 5px; +} + +/* line 82, ../sass/bootstrap/_tables.scss */ +.table-bordered { + border: 1px solid #ddd; +} +/* line 88, ../sass/bootstrap/_tables.scss */ +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > th, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > th, +.table-bordered > tfoot > tr > td { + border: 1px solid #ddd; +} +/* line 95, ../sass/bootstrap/_tables.scss */ +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} + +/* line 109, ../sass/bootstrap/_tables.scss */ +.table-striped > tbody > tr:nth-child(odd) > td, +.table-striped > tbody > tr:nth-child(odd) > th { + background-color: #f9f9f9; +} + +/* line 123, ../sass/bootstrap/_tables.scss */ +.table-hover > tbody > tr:hover > td, +.table-hover > tbody > tr:hover > th { + background-color: #f5f5f5; +} + +/* line 135, ../sass/bootstrap/_tables.scss */ +table col[class*="col-"] { + position: static; + float: none; + display: table-column; +} + +/* line 143, ../sass/bootstrap/_tables.scss */ +table td[class*="col-"], +table th[class*="col-"] { + position: static; + float: none; + display: table-cell; +} + +/* line 9, ../sass/bootstrap/mixins/_table-row.scss */ +.table > thead > tr > td.active, +.table > thead > tr > th.active, .table > thead > tr.active > td, .table > thead > tr.active > th, +.table > tbody > tr > td.active, +.table > tbody > tr > th.active, +.table > tbody > tr.active > td, +.table > tbody > tr.active > th, +.table > tfoot > tr > td.active, +.table > tfoot > tr > th.active, +.table > tfoot > tr.active > td, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} + +/* line 20, ../sass/bootstrap/mixins/_table-row.scss */ +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, .table-hover > tbody > tr.active:hover > td, .table-hover > tbody > tr:hover > .active, .table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; +} + +/* line 9, ../sass/bootstrap/mixins/_table-row.scss */ +.table > thead > tr > td.success, +.table > thead > tr > th.success, .table > thead > tr.success > td, .table > thead > tr.success > th, +.table > tbody > tr > td.success, +.table > tbody > tr > th.success, +.table > tbody > tr.success > td, +.table > tbody > tr.success > th, +.table > tfoot > tr > td.success, +.table > tfoot > tr > th.success, +.table > tfoot > tr.success > td, +.table > tfoot > tr.success > th { + background-color: #dff0d8; +} + +/* line 20, ../sass/bootstrap/mixins/_table-row.scss */ +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, .table-hover > tbody > tr.success:hover > td, .table-hover > tbody > tr:hover > .success, .table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; +} + +/* line 9, ../sass/bootstrap/mixins/_table-row.scss */ +.table > thead > tr > td.info, +.table > thead > tr > th.info, .table > thead > tr.info > td, .table > thead > tr.info > th, +.table > tbody > tr > td.info, +.table > tbody > tr > th.info, +.table > tbody > tr.info > td, +.table > tbody > tr.info > th, +.table > tfoot > tr > td.info, +.table > tfoot > tr > th.info, +.table > tfoot > tr.info > td, +.table > tfoot > tr.info > th { + background-color: #d9edf7; +} + +/* line 20, ../sass/bootstrap/mixins/_table-row.scss */ +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, .table-hover > tbody > tr.info:hover > td, .table-hover > tbody > tr:hover > .info, .table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; +} + +/* line 9, ../sass/bootstrap/mixins/_table-row.scss */ +.table > thead > tr > td.warning, +.table > thead > tr > th.warning, .table > thead > tr.warning > td, .table > thead > tr.warning > th, +.table > tbody > tr > td.warning, +.table > tbody > tr > th.warning, +.table > tbody > tr.warning > td, +.table > tbody > tr.warning > th, +.table > tfoot > tr > td.warning, +.table > tfoot > tr > th.warning, +.table > tfoot > tr.warning > td, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; +} + +/* line 20, ../sass/bootstrap/mixins/_table-row.scss */ +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, .table-hover > tbody > tr.warning:hover > td, .table-hover > tbody > tr:hover > .warning, .table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; +} + +/* line 9, ../sass/bootstrap/mixins/_table-row.scss */ +.table > thead > tr > td.danger, +.table > thead > tr > th.danger, .table > thead > tr.danger > td, .table > thead > tr.danger > th, +.table > tbody > tr > td.danger, +.table > tbody > tr > th.danger, +.table > tbody > tr.danger > td, +.table > tbody > tr.danger > th, +.table > tfoot > tr > td.danger, +.table > tfoot > tr > th.danger, +.table > tfoot > tr.danger > td, +.table > tfoot > tr.danger > th { + background-color: #f2dede; +} + +/* line 20, ../sass/bootstrap/mixins/_table-row.scss */ +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, .table-hover > tbody > tr.danger:hover > td, .table-hover > tbody > tr:hover > .danger, .table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; +} + +@media screen and (max-width: 767px) { + /* line 171, ../sass/bootstrap/_tables.scss */ + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + overflow-x: auto; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #ddd; + -webkit-overflow-scrolling: touch; + } + /* line 182, ../sass/bootstrap/_tables.scss */ + .table-responsive > .table { + margin-bottom: 0; + } + /* line 190, ../sass/bootstrap/_tables.scss */ + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + /* line 199, ../sass/bootstrap/_tables.scss */ + .table-responsive > .table-bordered { + border: 0; + } + /* line 207, ../sass/bootstrap/_tables.scss */ + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + /* line 211, ../sass/bootstrap/_tables.scss */ + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + /* line 224, ../sass/bootstrap/_tables.scss */ + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} + +/* line 10, ../sass/bootstrap/_forms.scss */ +fieldset { + padding: 0; + margin: 0; + border: 0; + min-width: 0; +} + +/* line 20, ../sass/bootstrap/_forms.scss */ +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} + +/* line 32, ../sass/bootstrap/_forms.scss */ +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: bold; +} + +/* line 47, ../sass/bootstrap/_forms.scss */ +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +/* line 52, ../sass/bootstrap/_forms.scss */ +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; +} + +/* line 60, ../sass/bootstrap/_forms.scss */ +input[type="file"] { + display: block; +} + +/* line 65, ../sass/bootstrap/_forms.scss */ +input[type="range"] { + display: block; + width: 100%; +} + +/* line 71, ../sass/bootstrap/_forms.scss */ +select[multiple], +select[size] { + height: auto; +} + +/* line 77, ../sass/bootstrap/_forms.scss */ +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +/* line 84, ../sass/bootstrap/_forms.scss */ +output { + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.42857; + color: #555555; +} + +/* line 115, ../sass/bootstrap/_forms.scss */ +.form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857; + color: #555555; + background-color: #fff; + background-image: none; + border: 1px solid #ccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; + -o-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; + transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; +} +/* line 53, ../sass/bootstrap/mixins/_forms.scss */ +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6); +} +/* line 102, ../sass/bootstrap/mixins/_vendor-prefixes.scss */ +.form-control::-moz-placeholder { + color: #777777; + opacity: 1; +} +/* line 104, ../sass/bootstrap/mixins/_vendor-prefixes.scss */ +.form-control:-ms-input-placeholder { + color: #777777; +} +/* line 105, ../sass/bootstrap/mixins/_vendor-prefixes.scss */ +.form-control::-webkit-input-placeholder { + color: #777777; +} +/* line 141, ../sass/bootstrap/_forms.scss */ +.form-control[disabled], .form-control[readonly], fieldset[disabled] .form-control { + cursor: not-allowed; + background-color: #eeeeee; + opacity: 1; +} + +/* line 153, ../sass/bootstrap/_forms.scss */ +textarea.form-control { + height: auto; +} + +/* line 165, ../sass/bootstrap/_forms.scss */ +input[type="search"] { + -webkit-appearance: none; +} + +/* line 178, ../sass/bootstrap/_forms.scss */ +input[type="date"], +input[type="time"], +input[type="datetime-local"], +input[type="month"] { + line-height: 34px; + line-height: 1.42857 \0; +} +/* line 186, ../sass/bootstrap/_forms.scss */ +input[type="date"].input-sm, .form-horizontal .form-group-sm input[type="date"].form-control, .input-group-sm > input[type="date"].form-control, +.input-group-sm > input[type="date"].input-group-addon, +.input-group-sm > .input-group-btn > input[type="date"].btn, +input[type="time"].input-sm, +.form-horizontal .form-group-sm input[type="time"].form-control, +.input-group-sm > input[type="time"].form-control, +.input-group-sm > input[type="time"].input-group-addon, +.input-group-sm > .input-group-btn > input[type="time"].btn, +input[type="datetime-local"].input-sm, +.form-horizontal .form-group-sm input[type="datetime-local"].form-control, +.input-group-sm > input[type="datetime-local"].form-control, +.input-group-sm > input[type="datetime-local"].input-group-addon, +.input-group-sm > .input-group-btn > input[type="datetime-local"].btn, +input[type="month"].input-sm, +.form-horizontal .form-group-sm input[type="month"].form-control, +.input-group-sm > input[type="month"].form-control, +.input-group-sm > input[type="month"].input-group-addon, +.input-group-sm > .input-group-btn > input[type="month"].btn { + line-height: 30px; +} +/* line 189, ../sass/bootstrap/_forms.scss */ +input[type="date"].input-lg, .form-horizontal .form-group-lg input[type="date"].form-control, .input-group-lg > input[type="date"].form-control, +.input-group-lg > input[type="date"].input-group-addon, +.input-group-lg > .input-group-btn > input[type="date"].btn, +input[type="time"].input-lg, +.form-horizontal .form-group-lg input[type="time"].form-control, +.input-group-lg > input[type="time"].form-control, +.input-group-lg > input[type="time"].input-group-addon, +.input-group-lg > .input-group-btn > input[type="time"].btn, +input[type="datetime-local"].input-lg, +.form-horizontal .form-group-lg input[type="datetime-local"].form-control, +.input-group-lg > input[type="datetime-local"].form-control, +.input-group-lg > input[type="datetime-local"].input-group-addon, +.input-group-lg > .input-group-btn > input[type="datetime-local"].btn, +input[type="month"].input-lg, +.form-horizontal .form-group-lg input[type="month"].form-control, +.input-group-lg > input[type="month"].form-control, +.input-group-lg > input[type="month"].input-group-addon, +.input-group-lg > .input-group-btn > input[type="month"].btn { + line-height: 46px; +} + +/* line 200, ../sass/bootstrap/_forms.scss */ +.form-group { + margin-bottom: 15px; +} + +/* line 209, ../sass/bootstrap/_forms.scss */ +.radio, +.checkbox { + position: relative; + display: block; + min-height: 20px; + margin-top: 10px; + margin-bottom: 10px; +} +/* line 217, ../sass/bootstrap/_forms.scss */ +.radio label, +.checkbox label { + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; +} + +/* line 224, ../sass/bootstrap/_forms.scss */ +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + position: absolute; + margin-left: -20px; + margin-top: 4px \9; +} + +/* line 233, ../sass/bootstrap/_forms.scss */ +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} + +/* line 239, ../sass/bootstrap/_forms.scss */ +.radio-inline, +.checkbox-inline { + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + vertical-align: middle; + font-weight: normal; + cursor: pointer; +} + +/* line 248, ../sass/bootstrap/_forms.scss */ +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} + +/* line 260, ../sass/bootstrap/_forms.scss */ +input[type="radio"][disabled], input[type="radio"].disabled, fieldset[disabled] input[type="radio"], +input[type="checkbox"][disabled], +input[type="checkbox"].disabled, fieldset[disabled] +input[type="checkbox"] { + cursor: not-allowed; +} + +/* line 269, ../sass/bootstrap/_forms.scss */ +.radio-inline.disabled, fieldset[disabled] .radio-inline, +.checkbox-inline.disabled, fieldset[disabled] +.checkbox-inline { + cursor: not-allowed; +} + +/* line 279, ../sass/bootstrap/_forms.scss */ +.radio.disabled label, fieldset[disabled] .radio label, +.checkbox.disabled label, fieldset[disabled] +.checkbox label { + cursor: not-allowed; +} + +/* line 291, ../sass/bootstrap/_forms.scss */ +.form-control-static { + padding-top: 7px; + padding-bottom: 7px; + margin-bottom: 0; +} +/* line 298, ../sass/bootstrap/_forms.scss */ +.form-control-static.input-lg, .form-horizontal .form-group-lg .form-control-static.form-control, .input-group-lg > .form-control-static.form-control, +.input-group-lg > .form-control-static.input-group-addon, +.input-group-lg > .input-group-btn > .form-control-static.btn, .form-control-static.input-sm, .form-horizontal .form-group-sm .form-control-static.form-control, .input-group-sm > .form-control-static.form-control, +.input-group-sm > .form-control-static.input-group-addon, +.input-group-sm > .input-group-btn > .form-control-static.btn { + padding-left: 0; + padding-right: 0; +} + +/* line 67, ../sass/bootstrap/mixins/_forms.scss */ +.input-sm, .form-horizontal .form-group-sm .form-control, .input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} + +/* line 75, ../sass/bootstrap/mixins/_forms.scss */ +select.input-sm, .form-horizontal .form-group-sm select.form-control, .input-group-sm > select.form-control, +.input-group-sm > select.input-group-addon, +.input-group-sm > .input-group-btn > select.btn { + height: 30px; + line-height: 30px; +} + +/* line 80, ../sass/bootstrap/mixins/_forms.scss */ +textarea.input-sm, .form-horizontal .form-group-sm textarea.form-control, .input-group-sm > textarea.form-control, +.input-group-sm > textarea.input-group-addon, +.input-group-sm > .input-group-btn > textarea.btn, +select[multiple].input-sm, +.form-horizontal .form-group-sm select[multiple].form-control, +.input-group-sm > select[multiple].form-control, +.input-group-sm > select[multiple].input-group-addon, +.input-group-sm > .input-group-btn > select[multiple].btn { + height: auto; +} + +/* line 67, ../sass/bootstrap/mixins/_forms.scss */ +.input-lg, .form-horizontal .form-group-lg .form-control, .input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} + +/* line 75, ../sass/bootstrap/mixins/_forms.scss */ +select.input-lg, .form-horizontal .form-group-lg select.form-control, .input-group-lg > select.form-control, +.input-group-lg > select.input-group-addon, +.input-group-lg > .input-group-btn > select.btn { + height: 46px; + line-height: 46px; +} + +/* line 80, ../sass/bootstrap/mixins/_forms.scss */ +textarea.input-lg, .form-horizontal .form-group-lg textarea.form-control, .input-group-lg > textarea.form-control, +.input-group-lg > textarea.input-group-addon, +.input-group-lg > .input-group-btn > textarea.btn, +select[multiple].input-lg, +.form-horizontal .form-group-lg select[multiple].form-control, +.input-group-lg > select[multiple].form-control, +.input-group-lg > select[multiple].input-group-addon, +.input-group-lg > .input-group-btn > select[multiple].btn { + height: auto; +} + +/* line 320, ../sass/bootstrap/_forms.scss */ +.has-feedback { + position: relative; +} +/* line 325, ../sass/bootstrap/_forms.scss */ +.has-feedback .form-control { + padding-right: 42.5px; +} + +/* line 330, ../sass/bootstrap/_forms.scss */ +.form-control-feedback { + position: absolute; + top: 25px; + right: 0; + z-index: 2; + display: block; + width: 34px; + height: 34px; + line-height: 34px; + text-align: center; +} + +/* line 341, ../sass/bootstrap/_forms.scss */ +.input-lg + .form-control-feedback, .form-horizontal .form-group-lg .form-control + .form-control-feedback, .input-group-lg > .form-control + .form-control-feedback, +.input-group-lg > .input-group-addon + .form-control-feedback, +.input-group-lg > .input-group-btn > .btn + .form-control-feedback { + width: 46px; + height: 46px; + line-height: 46px; +} + +/* line 346, ../sass/bootstrap/_forms.scss */ +.input-sm + .form-control-feedback, .form-horizontal .form-group-sm .form-control + .form-control-feedback, .input-group-sm > .form-control + .form-control-feedback, +.input-group-sm > .input-group-addon + .form-control-feedback, +.input-group-sm > .input-group-btn > .btn + .form-control-feedback { + width: 30px; + height: 30px; + line-height: 30px; +} + +/* line 8, ../sass/bootstrap/mixins/_forms.scss */ +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline { + color: #3c763d; +} +/* line 17, ../sass/bootstrap/mixins/_forms.scss */ +.has-success .form-control { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +/* line 20, ../sass/bootstrap/mixins/_forms.scss */ +.has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; +} +/* line 27, ../sass/bootstrap/mixins/_forms.scss */ +.has-success .input-group-addon { + color: #3c763d; + border-color: #3c763d; + background-color: #dff0d8; +} +/* line 33, ../sass/bootstrap/mixins/_forms.scss */ +.has-success .form-control-feedback { + color: #3c763d; +} + +/* line 8, ../sass/bootstrap/mixins/_forms.scss */ +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline { + color: #8a6d3b; +} +/* line 17, ../sass/bootstrap/mixins/_forms.scss */ +.has-warning .form-control { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +/* line 20, ../sass/bootstrap/mixins/_forms.scss */ +.has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; +} +/* line 27, ../sass/bootstrap/mixins/_forms.scss */ +.has-warning .input-group-addon { + color: #8a6d3b; + border-color: #8a6d3b; + background-color: #fcf8e3; +} +/* line 33, ../sass/bootstrap/mixins/_forms.scss */ +.has-warning .form-control-feedback { + color: #8a6d3b; +} + +/* line 8, ../sass/bootstrap/mixins/_forms.scss */ +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline { + color: #a94442; +} +/* line 17, ../sass/bootstrap/mixins/_forms.scss */ +.has-error .form-control { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +/* line 20, ../sass/bootstrap/mixins/_forms.scss */ +.has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; +} +/* line 27, ../sass/bootstrap/mixins/_forms.scss */ +.has-error .input-group-addon { + color: #a94442; + border-color: #a94442; + background-color: #f2dede; +} +/* line 33, ../sass/bootstrap/mixins/_forms.scss */ +.has-error .form-control-feedback { + color: #a94442; +} + +/* line 365, ../sass/bootstrap/_forms.scss */ +.has-feedback label.sr-only ~ .form-control-feedback { + top: 0; +} + +/* line 375, ../sass/bootstrap/_forms.scss */ +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; +} + +@media (min-width: 768px) { + /* line 400, ../sass/bootstrap/_forms.scss */ + .form-inline .form-group, .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + /* line 407, ../sass/bootstrap/_forms.scss */ + .form-inline .form-control, .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + /* line 413, ../sass/bootstrap/_forms.scss */ + .form-inline .input-group, .navbar-form .input-group { + display: inline-table; + vertical-align: middle; + } + /* line 417, ../sass/bootstrap/_forms.scss */ + .form-inline .input-group .input-group-addon, .navbar-form .input-group .input-group-addon, + .form-inline .input-group .input-group-btn, + .navbar-form .input-group .input-group-btn, + .form-inline .input-group .form-control, + .navbar-form .input-group .form-control { + width: auto; + } + /* line 425, ../sass/bootstrap/_forms.scss */ + .form-inline .input-group > .form-control, .navbar-form .input-group > .form-control { + width: 100%; + } + /* line 429, ../sass/bootstrap/_forms.scss */ + .form-inline .control-label, .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + /* line 437, ../sass/bootstrap/_forms.scss */ + .form-inline .radio, .navbar-form .radio, + .form-inline .checkbox, + .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + /* line 444, ../sass/bootstrap/_forms.scss */ + .form-inline .radio label, .navbar-form .radio label, + .form-inline .checkbox label, + .navbar-form .checkbox label { + padding-left: 0; + } + /* line 448, ../sass/bootstrap/_forms.scss */ + .form-inline .radio input[type="radio"], .navbar-form .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"], + .navbar-form .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + /* line 458, ../sass/bootstrap/_forms.scss */ + .form-inline .has-feedback .form-control-feedback, .navbar-form .has-feedback .form-control-feedback { + top: 0; + } +} + +/* line 475, ../sass/bootstrap/_forms.scss */ +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + margin-top: 0; + margin-bottom: 0; + padding-top: 7px; +} +/* line 485, ../sass/bootstrap/_forms.scss */ +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 27px; +} +/* line 491, ../sass/bootstrap/_forms.scss */ +.form-horizontal .form-group { + margin-left: -15px; + margin-right: -15px; +} +/* line 14, ../sass/bootstrap/mixins/_clearfix.scss */ +.form-horizontal .form-group:before, .form-horizontal .form-group:after { + content: " "; + display: table; +} +/* line 19, ../sass/bootstrap/mixins/_clearfix.scss */ +.form-horizontal .form-group:after { + clear: both; +} +@media (min-width: 768px) { + /* line 498, ../sass/bootstrap/_forms.scss */ + .form-horizontal .control-label { + text-align: right; + margin-bottom: 0; + padding-top: 7px; + } +} +/* line 509, ../sass/bootstrap/_forms.scss */ +.form-horizontal .has-feedback .form-control-feedback { + top: 0; + right: 15px; +} +@media (min-width: 768px) { + /* line 520, ../sass/bootstrap/_forms.scss */ + .form-horizontal .form-group-lg .control-label { + padding-top: 14.3px; + } +} +@media (min-width: 768px) { + /* line 530, ../sass/bootstrap/_forms.scss */ + .form-horizontal .form-group-sm .control-label { + padding-top: 6px; + } +} + +/* line 9, ../sass/bootstrap/_buttons.scss */ +.btn { + display: inline-block; + margin-bottom: 0; + font-weight: normal; + text-align: center; + vertical-align: middle; + cursor: pointer; + background-image: none; + border: 1px solid transparent; + white-space: nowrap; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857; + border-radius: 4px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +/* line 25, ../sass/bootstrap/_buttons.scss */ +.btn:focus, .btn:active:focus, .btn.active:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +/* line 30, ../sass/bootstrap/_buttons.scss */ +.btn:hover, .btn:focus { + color: #333; + text-decoration: none; +} +/* line 36, ../sass/bootstrap/_buttons.scss */ +.btn:active, .btn.active { + outline: 0; + background-image: none; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +/* line 43, ../sass/bootstrap/_buttons.scss */ +.btn.disabled, .btn[disabled], fieldset[disabled] .btn { + cursor: not-allowed; + pointer-events: none; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; +} + +/* line 57, ../sass/bootstrap/_buttons.scss */ +.btn-default { + color: #333; + background-color: #fff; + border-color: #ccc; +} +/* line 11, ../sass/bootstrap/mixins/_buttons.scss */ +.btn-default:hover, .btn-default:focus, .btn-default:active, .btn-default.active, .open > .btn-default.dropdown-toggle { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} +/* line 20, ../sass/bootstrap/mixins/_buttons.scss */ +.btn-default:active, .btn-default.active, .open > .btn-default.dropdown-toggle { + background-image: none; +} +/* line 28, ../sass/bootstrap/mixins/_buttons.scss */ +.btn-default.disabled, .btn-default.disabled:hover, .btn-default.disabled:focus, .btn-default.disabled:active, .btn-default.disabled.active, .btn-default[disabled], .btn-default[disabled]:hover, .btn-default[disabled]:focus, .btn-default[disabled]:active, .btn-default[disabled].active, fieldset[disabled] .btn-default, fieldset[disabled] .btn-default:hover, fieldset[disabled] .btn-default:focus, fieldset[disabled] .btn-default:active, fieldset[disabled] .btn-default.active { + background-color: #fff; + border-color: #ccc; +} +/* line 38, ../sass/bootstrap/mixins/_buttons.scss */ +.btn-default .badge { + color: #fff; + background-color: #333; +} + +/* line 60, ../sass/bootstrap/_buttons.scss */ +.btn-primary { + color: #fff; + background-color: #428bca; + border-color: #357ebd; +} +/* line 11, ../sass/bootstrap/mixins/_buttons.scss */ +.btn-primary:hover, .btn-primary:focus, .btn-primary:active, .btn-primary.active, .open > .btn-primary.dropdown-toggle { + color: #fff; + background-color: #3071a9; + border-color: #285e8e; +} +/* line 20, ../sass/bootstrap/mixins/_buttons.scss */ +.btn-primary:active, .btn-primary.active, .open > .btn-primary.dropdown-toggle { + background-image: none; +} +/* line 28, ../sass/bootstrap/mixins/_buttons.scss */ +.btn-primary.disabled, .btn-primary.disabled:hover, .btn-primary.disabled:focus, .btn-primary.disabled:active, .btn-primary.disabled.active, .btn-primary[disabled], .btn-primary[disabled]:hover, .btn-primary[disabled]:focus, .btn-primary[disabled]:active, .btn-primary[disabled].active, fieldset[disabled] .btn-primary, fieldset[disabled] .btn-primary:hover, fieldset[disabled] .btn-primary:focus, fieldset[disabled] .btn-primary:active, fieldset[disabled] .btn-primary.active { + background-color: #428bca; + border-color: #357ebd; +} +/* line 38, ../sass/bootstrap/mixins/_buttons.scss */ +.btn-primary .badge { + color: #428bca; + background-color: #fff; +} + +/* line 64, ../sass/bootstrap/_buttons.scss */ +.btn-success { + color: #fff; + background-color: #5cb85c; + border-color: #4cae4c; +} +/* line 11, ../sass/bootstrap/mixins/_buttons.scss */ +.btn-success:hover, .btn-success:focus, .btn-success:active, .btn-success.active, .open > .btn-success.dropdown-toggle { + color: #fff; + background-color: #449d44; + border-color: #398439; +} +/* line 20, ../sass/bootstrap/mixins/_buttons.scss */ +.btn-success:active, .btn-success.active, .open > .btn-success.dropdown-toggle { + background-image: none; +} +/* line 28, ../sass/bootstrap/mixins/_buttons.scss */ +.btn-success.disabled, .btn-success.disabled:hover, .btn-success.disabled:focus, .btn-success.disabled:active, .btn-success.disabled.active, .btn-success[disabled], .btn-success[disabled]:hover, .btn-success[disabled]:focus, .btn-success[disabled]:active, .btn-success[disabled].active, fieldset[disabled] .btn-success, fieldset[disabled] .btn-success:hover, fieldset[disabled] .btn-success:focus, fieldset[disabled] .btn-success:active, fieldset[disabled] .btn-success.active { + background-color: #5cb85c; + border-color: #4cae4c; +} +/* line 38, ../sass/bootstrap/mixins/_buttons.scss */ +.btn-success .badge { + color: #5cb85c; + background-color: #fff; +} + +/* line 68, ../sass/bootstrap/_buttons.scss */ +.btn-info { + color: #fff; + background-color: #5bc0de; + border-color: #46b8da; +} +/* line 11, ../sass/bootstrap/mixins/_buttons.scss */ +.btn-info:hover, .btn-info:focus, .btn-info:active, .btn-info.active, .open > .btn-info.dropdown-toggle { + color: #fff; + background-color: #31b0d5; + border-color: #269abc; +} +/* line 20, ../sass/bootstrap/mixins/_buttons.scss */ +.btn-info:active, .btn-info.active, .open > .btn-info.dropdown-toggle { + background-image: none; +} +/* line 28, ../sass/bootstrap/mixins/_buttons.scss */ +.btn-info.disabled, .btn-info.disabled:hover, .btn-info.disabled:focus, .btn-info.disabled:active, .btn-info.disabled.active, .btn-info[disabled], .btn-info[disabled]:hover, .btn-info[disabled]:focus, .btn-info[disabled]:active, .btn-info[disabled].active, fieldset[disabled] .btn-info, fieldset[disabled] .btn-info:hover, fieldset[disabled] .btn-info:focus, fieldset[disabled] .btn-info:active, fieldset[disabled] .btn-info.active { + background-color: #5bc0de; + border-color: #46b8da; +} +/* line 38, ../sass/bootstrap/mixins/_buttons.scss */ +.btn-info .badge { + color: #5bc0de; + background-color: #fff; +} + +/* line 72, ../sass/bootstrap/_buttons.scss */ +.btn-warning { + color: #fff; + background-color: #f0ad4e; + border-color: #eea236; +} +/* line 11, ../sass/bootstrap/mixins/_buttons.scss */ +.btn-warning:hover, .btn-warning:focus, .btn-warning:active, .btn-warning.active, .open > .btn-warning.dropdown-toggle { + color: #fff; + background-color: #ec971f; + border-color: #d58512; +} +/* line 20, ../sass/bootstrap/mixins/_buttons.scss */ +.btn-warning:active, .btn-warning.active, .open > .btn-warning.dropdown-toggle { + background-image: none; +} +/* line 28, ../sass/bootstrap/mixins/_buttons.scss */ +.btn-warning.disabled, .btn-warning.disabled:hover, .btn-warning.disabled:focus, .btn-warning.disabled:active, .btn-warning.disabled.active, .btn-warning[disabled], .btn-warning[disabled]:hover, .btn-warning[disabled]:focus, .btn-warning[disabled]:active, .btn-warning[disabled].active, fieldset[disabled] .btn-warning, fieldset[disabled] .btn-warning:hover, fieldset[disabled] .btn-warning:focus, fieldset[disabled] .btn-warning:active, fieldset[disabled] .btn-warning.active { + background-color: #f0ad4e; + border-color: #eea236; +} +/* line 38, ../sass/bootstrap/mixins/_buttons.scss */ +.btn-warning .badge { + color: #f0ad4e; + background-color: #fff; +} + +/* line 76, ../sass/bootstrap/_buttons.scss */ +.btn-danger { + color: #fff; + background-color: #d9534f; + border-color: #d43f3a; +} +/* line 11, ../sass/bootstrap/mixins/_buttons.scss */ +.btn-danger:hover, .btn-danger:focus, .btn-danger:active, .btn-danger.active, .open > .btn-danger.dropdown-toggle { + color: #fff; + background-color: #c9302c; + border-color: #ac2925; +} +/* line 20, ../sass/bootstrap/mixins/_buttons.scss */ +.btn-danger:active, .btn-danger.active, .open > .btn-danger.dropdown-toggle { + background-image: none; +} +/* line 28, ../sass/bootstrap/mixins/_buttons.scss */ +.btn-danger.disabled, .btn-danger.disabled:hover, .btn-danger.disabled:focus, .btn-danger.disabled:active, .btn-danger.disabled.active, .btn-danger[disabled], .btn-danger[disabled]:hover, .btn-danger[disabled]:focus, .btn-danger[disabled]:active, .btn-danger[disabled].active, fieldset[disabled] .btn-danger, fieldset[disabled] .btn-danger:hover, fieldset[disabled] .btn-danger:focus, fieldset[disabled] .btn-danger:active, fieldset[disabled] .btn-danger.active { + background-color: #d9534f; + border-color: #d43f3a; +} +/* line 38, ../sass/bootstrap/mixins/_buttons.scss */ +.btn-danger .badge { + color: #d9534f; + background-color: #fff; +} + +/* line 85, ../sass/bootstrap/_buttons.scss */ +.btn-link { + color: #428bca; + font-weight: normal; + cursor: pointer; + border-radius: 0; +} +/* line 91, ../sass/bootstrap/_buttons.scss */ +.btn-link, .btn-link:active, .btn-link[disabled], fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +/* line 98, ../sass/bootstrap/_buttons.scss */ +.btn-link, .btn-link:hover, .btn-link:focus, .btn-link:active { + border-color: transparent; +} +/* line 104, ../sass/bootstrap/_buttons.scss */ +.btn-link:hover, .btn-link:focus { + color: #2a6496; + text-decoration: underline; + background-color: transparent; +} +/* line 112, ../sass/bootstrap/_buttons.scss */ +.btn-link[disabled]:hover, .btn-link[disabled]:focus, fieldset[disabled] .btn-link:hover, fieldset[disabled] .btn-link:focus { + color: #777777; + text-decoration: none; +} + +/* line 124, ../sass/bootstrap/_buttons.scss */ +.btn-lg, .btn-group-lg > .btn { + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} + +/* line 128, ../sass/bootstrap/_buttons.scss */ +.btn-sm, .btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} + +/* line 132, ../sass/bootstrap/_buttons.scss */ +.btn-xs, .btn-group-xs > .btn { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} + +/* line 140, ../sass/bootstrap/_buttons.scss */ +.btn-block { + display: block; + width: 100%; +} + +/* line 146, ../sass/bootstrap/_buttons.scss */ +.btn-block + .btn-block { + margin-top: 5px; +} + +/* line 154, ../sass/bootstrap/_buttons.scss */ +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} + +/* line 10, ../sass/bootstrap/_component-animations.scss */ +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} +/* line 13, ../sass/bootstrap/_component-animations.scss */ +.fade.in { + opacity: 1; +} + +/* line 18, ../sass/bootstrap/_component-animations.scss */ +.collapse { + display: none; +} +/* line 21, ../sass/bootstrap/_component-animations.scss */ +.collapse.in { + display: block; +} + +/* line 26, ../sass/bootstrap/_component-animations.scss */ +tr.collapse.in { + display: table-row; +} + +/* line 28, ../sass/bootstrap/_component-animations.scss */ +tbody.collapse.in { + display: table-row-group; +} + +/* line 30, ../sass/bootstrap/_component-animations.scss */ +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height 0.35s ease; + -o-transition: height 0.35s ease; + transition: height 0.35s ease; +} + +/* line 7, ../sass/bootstrap/_dropdowns.scss */ +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px solid; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} + +/* line 19, ../sass/bootstrap/_dropdowns.scss */ +.dropdown { + position: relative; +} + +/* line 24, ../sass/bootstrap/_dropdowns.scss */ +.dropdown-toggle:focus { + outline: 0; +} + +/* line 29, ../sass/bootstrap/_dropdowns.scss */ +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + font-size: 14px; + text-align: left; + background-color: #fff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + background-clip: padding-box; +} +/* line 52, ../sass/bootstrap/_dropdowns.scss */ +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +/* line 58, ../sass/bootstrap/_dropdowns.scss */ +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +/* line 63, ../sass/bootstrap/_dropdowns.scss */ +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857; + color: #333333; + white-space: nowrap; +} + +/* line 76, ../sass/bootstrap/_dropdowns.scss */ +.dropdown-menu > li > a:hover, .dropdown-menu > li > a:focus { + text-decoration: none; + color: #262626; + background-color: #f5f5f5; +} + +/* line 86, ../sass/bootstrap/_dropdowns.scss */ +.dropdown-menu > .active > a, .dropdown-menu > .active > a:hover, .dropdown-menu > .active > a:focus { + color: #fff; + text-decoration: none; + outline: 0; + background-color: #428bca; +} + +/* line 101, ../sass/bootstrap/_dropdowns.scss */ +.dropdown-menu > .disabled > a, .dropdown-menu > .disabled > a:hover, .dropdown-menu > .disabled > a:focus { + color: #777777; +} + +/* line 109, ../sass/bootstrap/_dropdowns.scss */ +.dropdown-menu > .disabled > a:hover, .dropdown-menu > .disabled > a:focus { + text-decoration: none; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + cursor: not-allowed; +} + +/* line 122, ../sass/bootstrap/_dropdowns.scss */ +.open > .dropdown-menu { + display: block; +} +/* line 127, ../sass/bootstrap/_dropdowns.scss */ +.open > a { + outline: 0; +} + +/* line 136, ../sass/bootstrap/_dropdowns.scss */ +.dropdown-menu-right { + left: auto; + right: 0; +} + +/* line 146, ../sass/bootstrap/_dropdowns.scss */ +.dropdown-menu-left { + left: 0; + right: auto; +} + +/* line 152, ../sass/bootstrap/_dropdowns.scss */ +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857; + color: #777777; + white-space: nowrap; +} + +/* line 162, ../sass/bootstrap/_dropdowns.scss */ +.dropdown-backdrop { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: 990; +} + +/* line 172, ../sass/bootstrap/_dropdowns.scss */ +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} + +/* line 185, ../sass/bootstrap/_dropdowns.scss */ +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px solid; + content: ""; +} +/* line 191, ../sass/bootstrap/_dropdowns.scss */ +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 1px; +} + +@media (min-width: 768px) { + /* line 205, ../sass/bootstrap/_dropdowns.scss */ + .navbar-right .dropdown-menu { + right: 0; + left: auto; + } + /* line 210, ../sass/bootstrap/_dropdowns.scss */ + .navbar-right .dropdown-menu-left { + left: 0; + right: auto; + } +} +/* line 6, ../sass/bootstrap/_button-groups.scss */ +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} +/* line 11, ../sass/bootstrap/_button-groups.scss */ +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} +/* line 15, ../sass/bootstrap/_button-groups.scss */ +.btn-group > .btn:hover, .btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active, +.btn-group-vertical > .btn:hover, +.btn-group-vertical > .btn:focus, +.btn-group-vertical > .btn:active, +.btn-group-vertical > .btn.active { + z-index: 2; +} +/* line 21, ../sass/bootstrap/_button-groups.scss */ +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus { + outline: 0; +} + +/* line 30, ../sass/bootstrap/_button-groups.scss */ +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} + +/* line 39, ../sass/bootstrap/_button-groups.scss */ +.btn-toolbar { + margin-left: -5px; +} +/* line 14, ../sass/bootstrap/mixins/_clearfix.scss */ +.btn-toolbar:before, .btn-toolbar:after { + content: " "; + display: table; +} +/* line 19, ../sass/bootstrap/mixins/_clearfix.scss */ +.btn-toolbar:after { + clear: both; +} +/* line 43, ../sass/bootstrap/_button-groups.scss */ +.btn-toolbar .btn-group, +.btn-toolbar .input-group { + float: left; +} +/* line 47, ../sass/bootstrap/_button-groups.scss */ +.btn-toolbar > .btn, +.btn-toolbar > .btn-group, +.btn-toolbar > .input-group { + margin-left: 5px; +} + +/* line 54, ../sass/bootstrap/_button-groups.scss */ +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} + +/* line 59, ../sass/bootstrap/_button-groups.scss */ +.btn-group > .btn:first-child { + margin-left: 0; +} +/* line 61, ../sass/bootstrap/_button-groups.scss */ +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} + +/* line 66, ../sass/bootstrap/_button-groups.scss */ +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} + +/* line 72, ../sass/bootstrap/_button-groups.scss */ +.btn-group > .btn-group { + float: left; +} + +/* line 75, ../sass/bootstrap/_button-groups.scss */ +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} + +/* line 79, ../sass/bootstrap/_button-groups.scss */ +.btn-group > .btn-group:first-child > .btn:last-child, +.btn-group > .btn-group:first-child > .dropdown-toggle { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} + +/* line 84, ../sass/bootstrap/_button-groups.scss */ +.btn-group > .btn-group:last-child > .btn:first-child { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} + +/* line 89, ../sass/bootstrap/_button-groups.scss */ +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} + +/* line 108, ../sass/bootstrap/_button-groups.scss */ +.btn-group > .btn + .dropdown-toggle { + padding-left: 8px; + padding-right: 8px; +} + +/* line 112, ../sass/bootstrap/_button-groups.scss */ +.btn-group > .btn-lg + .dropdown-toggle, .btn-group-lg.btn-group > .btn + .dropdown-toggle { + padding-left: 12px; + padding-right: 12px; +} + +/* line 119, ../sass/bootstrap/_button-groups.scss */ +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +/* line 123, ../sass/bootstrap/_button-groups.scss */ +.btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; +} + +/* line 130, ../sass/bootstrap/_button-groups.scss */ +.btn .caret { + margin-left: 0; +} + +/* line 134, ../sass/bootstrap/_button-groups.scss */ +.btn-lg .caret, .btn-group-lg > .btn .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} + +/* line 139, ../sass/bootstrap/_button-groups.scss */ +.dropup .btn-lg .caret, .dropup .btn-group-lg > .btn .caret { + border-width: 0 5px 5px; +} + +/* line 148, ../sass/bootstrap/_button-groups.scss */ +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group, +.btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; +} +/* line 14, ../sass/bootstrap/mixins/_clearfix.scss */ +.btn-group-vertical > .btn-group:before, .btn-group-vertical > .btn-group:after { + content: " "; + display: table; +} +/* line 19, ../sass/bootstrap/mixins/_clearfix.scss */ +.btn-group-vertical > .btn-group:after { + clear: both; +} +/* line 160, ../sass/bootstrap/_button-groups.scss */ +.btn-group-vertical > .btn-group > .btn { + float: none; +} +/* line 165, ../sass/bootstrap/_button-groups.scss */ +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} + +/* line 175, ../sass/bootstrap/_button-groups.scss */ +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} +/* line 178, ../sass/bootstrap/_button-groups.scss */ +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +/* line 182, ../sass/bootstrap/_button-groups.scss */ +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-bottom-left-radius: 4px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} + +/* line 187, ../sass/bootstrap/_button-groups.scss */ +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} + +/* line 191, ../sass/bootstrap/_button-groups.scss */ +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +/* line 196, ../sass/bootstrap/_button-groups.scss */ +.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; +} + +/* line 205, ../sass/bootstrap/_button-groups.scss */ +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} +/* line 210, ../sass/bootstrap/_button-groups.scss */ +.btn-group-justified > .btn, +.btn-group-justified > .btn-group { + float: none; + display: table-cell; + width: 1%; +} +/* line 216, ../sass/bootstrap/_button-groups.scss */ +.btn-group-justified > .btn-group .btn { + width: 100%; +} +/* line 220, ../sass/bootstrap/_button-groups.scss */ +.btn-group-justified > .btn-group .dropdown-menu { + left: auto; +} + +/* line 235, ../sass/bootstrap/_button-groups.scss */ +[data-toggle="buttons"] > .btn > input[type="radio"], +[data-toggle="buttons"] > .btn > input[type="checkbox"] { + position: absolute; + z-index: -1; + opacity: 0; + filter: alpha(opacity=0); +} + +/* line 7, ../sass/bootstrap/_input-groups.scss */ +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +/* line 13, ../sass/bootstrap/_input-groups.scss */ +.input-group[class*="col-"] { + float: none; + padding-left: 0; + padding-right: 0; +} +/* line 19, ../sass/bootstrap/_input-groups.scss */ +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; +} + +/* line 54, ../sass/bootstrap/_input-groups.scss */ +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +/* line 59, ../sass/bootstrap/_input-groups.scss */ +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} + +/* line 64, ../sass/bootstrap/_input-groups.scss */ +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} + +/* line 73, ../sass/bootstrap/_input-groups.scss */ +.input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555555; + text-align: center; + background-color: #eeeeee; + border: 1px solid #ccc; + border-radius: 4px; +} +/* line 85, ../sass/bootstrap/_input-groups.scss */ +.input-group-addon.input-sm, .form-horizontal .form-group-sm .input-group-addon.form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .input-group-addon.btn { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; +} +/* line 90, ../sass/bootstrap/_input-groups.scss */ +.input-group-addon.input-lg, .form-horizontal .form-group-lg .input-group-addon.form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .input-group-addon.btn { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; +} +/* line 97, ../sass/bootstrap/_input-groups.scss */ +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} + +/* line 104, ../sass/bootstrap/_input-groups.scss */ +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} + +/* line 113, ../sass/bootstrap/_input-groups.scss */ +.input-group-addon:first-child { + border-right: 0; +} + +/* line 116, ../sass/bootstrap/_input-groups.scss */ +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} + +/* line 125, ../sass/bootstrap/_input-groups.scss */ +.input-group-addon:last-child { + border-left: 0; +} + +/* line 131, ../sass/bootstrap/_input-groups.scss */ +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +/* line 140, ../sass/bootstrap/_input-groups.scss */ +.input-group-btn > .btn { + position: relative; +} +/* line 142, ../sass/bootstrap/_input-groups.scss */ +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +/* line 146, ../sass/bootstrap/_input-groups.scss */ +.input-group-btn > .btn:hover, .input-group-btn > .btn:focus, .input-group-btn > .btn:active { + z-index: 2; +} +/* line 155, ../sass/bootstrap/_input-groups.scss */ +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +/* line 161, ../sass/bootstrap/_input-groups.scss */ +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + margin-left: -1px; +} + +/* line 9, ../sass/bootstrap/_navs.scss */ +.nav { + margin-bottom: 0; + padding-left: 0; + list-style: none; +} +/* line 14, ../sass/bootstrap/mixins/_clearfix.scss */ +.nav:before, .nav:after { + content: " "; + display: table; +} +/* line 19, ../sass/bootstrap/mixins/_clearfix.scss */ +.nav:after { + clear: both; +} +/* line 15, ../sass/bootstrap/_navs.scss */ +.nav > li { + position: relative; + display: block; +} +/* line 19, ../sass/bootstrap/_navs.scss */ +.nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} +/* line 23, ../sass/bootstrap/_navs.scss */ +.nav > li > a:hover, .nav > li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} +/* line 31, ../sass/bootstrap/_navs.scss */ +.nav > li.disabled > a { + color: #777777; +} +/* line 34, ../sass/bootstrap/_navs.scss */ +.nav > li.disabled > a:hover, .nav > li.disabled > a:focus { + color: #777777; + text-decoration: none; + background-color: transparent; + cursor: not-allowed; +} +/* line 46, ../sass/bootstrap/_navs.scss */ +.nav .open > a, .nav .open > a:hover, .nav .open > a:focus { + background-color: #eeeeee; + border-color: #428bca; +} +/* line 59, ../sass/bootstrap/_navs.scss */ +.nav .nav-divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +/* line 66, ../sass/bootstrap/_navs.scss */ +.nav > li > a > img { + max-width: none; +} + +/* line 76, ../sass/bootstrap/_navs.scss */ +.nav-tabs { + border-bottom: 1px solid #ddd; +} +/* line 78, ../sass/bootstrap/_navs.scss */ +.nav-tabs > li { + float: left; + margin-bottom: -1px; +} +/* line 84, ../sass/bootstrap/_navs.scss */ +.nav-tabs > li > a { + margin-right: 2px; + line-height: 1.42857; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; +} +/* line 89, ../sass/bootstrap/_navs.scss */ +.nav-tabs > li > a:hover { + border-color: #eeeeee #eeeeee #ddd; +} +/* line 96, ../sass/bootstrap/_navs.scss */ +.nav-tabs > li.active > a, .nav-tabs > li.active > a:hover, .nav-tabs > li.active > a:focus { + color: #555555; + background-color: #fff; + border: 1px solid #ddd; + border-bottom-color: transparent; + cursor: default; +} + +/* line 118, ../sass/bootstrap/_navs.scss */ +.nav-pills > li { + float: left; +} +/* line 122, ../sass/bootstrap/_navs.scss */ +.nav-pills > li > a { + border-radius: 4px; +} +/* line 125, ../sass/bootstrap/_navs.scss */ +.nav-pills > li + li { + margin-left: 2px; +} +/* line 131, ../sass/bootstrap/_navs.scss */ +.nav-pills > li.active > a, .nav-pills > li.active > a:hover, .nav-pills > li.active > a:focus { + color: #fff; + background-color: #428bca; +} + +/* line 144, ../sass/bootstrap/_navs.scss */ +.nav-stacked > li { + float: none; +} +/* line 146, ../sass/bootstrap/_navs.scss */ +.nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} + +/* line 160, ../sass/bootstrap/_navs.scss */ +.nav-justified, .nav-tabs.nav-justified { + width: 100%; +} +/* line 163, ../sass/bootstrap/_navs.scss */ +.nav-justified > li, .nav-tabs.nav-justified > li { + float: none; +} +/* line 165, ../sass/bootstrap/_navs.scss */ +.nav-justified > li > a, .nav-tabs.nav-justified > li > a { + text-align: center; + margin-bottom: 5px; +} +/* line 171, ../sass/bootstrap/_navs.scss */ +.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + /* line 177, ../sass/bootstrap/_navs.scss */ + .nav-justified > li, .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + /* line 180, ../sass/bootstrap/_navs.scss */ + .nav-justified > li > a, .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} + +/* line 190, ../sass/bootstrap/_navs.scss */ +.nav-tabs-justified, .nav-tabs.nav-justified { + border-bottom: 0; +} +/* line 193, ../sass/bootstrap/_navs.scss */ +.nav-tabs-justified > li > a, .nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +/* line 199, ../sass/bootstrap/_navs.scss */ +.nav-tabs-justified > .active > a, .nav-tabs.nav-justified > .active > a, +.nav-tabs-justified > .active > a:hover, +.nav-tabs.nav-justified > .active > a:hover, +.nav-tabs-justified > .active > a:focus, +.nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + /* line 206, ../sass/bootstrap/_navs.scss */ + .nav-tabs-justified > li > a, .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + /* line 210, ../sass/bootstrap/_navs.scss */ + .nav-tabs-justified > .active > a, .nav-tabs.nav-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #fff; + } +} + +/* line 224, ../sass/bootstrap/_navs.scss */ +.tab-content > .tab-pane { + display: none; +} +/* line 227, ../sass/bootstrap/_navs.scss */ +.tab-content > .active { + display: block; +} + +/* line 237, ../sass/bootstrap/_navs.scss */ +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} + +/* line 11, ../sass/bootstrap/_navbar.scss */ +.navbar { + position: relative; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent; +} +/* line 14, ../sass/bootstrap/mixins/_clearfix.scss */ +.navbar:before, .navbar:after { + content: " "; + display: table; +} +/* line 19, ../sass/bootstrap/mixins/_clearfix.scss */ +.navbar:after { + clear: both; +} +@media (min-width: 768px) { + /* line 11, ../sass/bootstrap/_navbar.scss */ + .navbar { + border-radius: 4px; + } +} + +/* line 14, ../sass/bootstrap/mixins/_clearfix.scss */ +.navbar-header:before, .navbar-header:after { + content: " "; + display: table; +} +/* line 19, ../sass/bootstrap/mixins/_clearfix.scss */ +.navbar-header:after { + clear: both; +} +@media (min-width: 768px) { + /* line 31, ../sass/bootstrap/_navbar.scss */ + .navbar-header { + float: left; + } +} + +/* line 50, ../sass/bootstrap/_navbar.scss */ +.navbar-collapse { + overflow-x: visible; + padding-right: 15px; + padding-left: 15px; + border-top: 1px solid transparent; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + -webkit-overflow-scrolling: touch; +} +/* line 14, ../sass/bootstrap/mixins/_clearfix.scss */ +.navbar-collapse:before, .navbar-collapse:after { + content: " "; + display: table; +} +/* line 19, ../sass/bootstrap/mixins/_clearfix.scss */ +.navbar-collapse:after { + clear: both; +} +/* line 59, ../sass/bootstrap/_navbar.scss */ +.navbar-collapse.in { + overflow-y: auto; +} +@media (min-width: 768px) { + /* line 50, ../sass/bootstrap/_navbar.scss */ + .navbar-collapse { + width: auto; + border-top: 0; + box-shadow: none; + } + /* line 68, ../sass/bootstrap/_navbar.scss */ + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + /* line 75, ../sass/bootstrap/_navbar.scss */ + .navbar-collapse.in { + overflow-y: visible; + } + /* line 81, ../sass/bootstrap/_navbar.scss */ + .navbar-fixed-top .navbar-collapse, .navbar-static-top .navbar-collapse, .navbar-fixed-bottom .navbar-collapse { + padding-left: 0; + padding-right: 0; + } +} + +/* line 92, ../sass/bootstrap/_navbar.scss */ +.navbar-fixed-top .navbar-collapse, +.navbar-fixed-bottom .navbar-collapse { + max-height: 340px; +} +@media (max-width: 480px) and (orientation: landscape) { + /* line 92, ../sass/bootstrap/_navbar.scss */ + .navbar-fixed-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + max-height: 200px; + } +} + +/* line 108, ../sass/bootstrap/_navbar.scss */ +.container > .navbar-header, +.container > .navbar-collapse, +.container-fluid > .navbar-header, +.container-fluid > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + /* line 108, ../sass/bootstrap/_navbar.scss */ + .container > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-header, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} + +/* line 128, ../sass/bootstrap/_navbar.scss */ +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; +} +@media (min-width: 768px) { + /* line 128, ../sass/bootstrap/_navbar.scss */ + .navbar-static-top { + border-radius: 0; + } +} + +/* line 138, ../sass/bootstrap/_navbar.scss */ +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); +} +@media (min-width: 768px) { + /* line 138, ../sass/bootstrap/_navbar.scss */ + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} + +/* line 151, ../sass/bootstrap/_navbar.scss */ +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} + +/* line 155, ../sass/bootstrap/_navbar.scss */ +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} + +/* line 164, ../sass/bootstrap/_navbar.scss */ +.navbar-brand { + float: left; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; + height: 50px; +} +/* line 171, ../sass/bootstrap/_navbar.scss */ +.navbar-brand:hover, .navbar-brand:focus { + text-decoration: none; +} +@media (min-width: 768px) { + /* line 177, ../sass/bootstrap/_navbar.scss */ + .navbar > .container .navbar-brand, .navbar > .container-fluid .navbar-brand { + margin-left: -15px; + } +} + +/* line 190, ../sass/bootstrap/_navbar.scss */ +.navbar-toggle { + position: relative; + float: right; + margin-right: 15px; + padding: 9px 10px; + margin-top: 8px; + margin-bottom: 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +/* line 203, ../sass/bootstrap/_navbar.scss */ +.navbar-toggle:focus { + outline: 0; +} +/* line 208, ../sass/bootstrap/_navbar.scss */ +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} +/* line 214, ../sass/bootstrap/_navbar.scss */ +.navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} +@media (min-width: 768px) { + /* line 190, ../sass/bootstrap/_navbar.scss */ + .navbar-toggle { + display: none; + } +} + +/* line 229, ../sass/bootstrap/_navbar.scss */ +.navbar-nav { + margin: 7.5px -15px; +} +/* line 232, ../sass/bootstrap/_navbar.scss */ +.navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; +} +@media (max-width: 767px) { + /* line 240, ../sass/bootstrap/_navbar.scss */ + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + box-shadow: none; + } + /* line 248, ../sass/bootstrap/_navbar.scss */ + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + /* line 252, ../sass/bootstrap/_navbar.scss */ + .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + /* line 254, ../sass/bootstrap/_navbar.scss */ + .navbar-nav .open .dropdown-menu > li > a:hover, .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} +@media (min-width: 768px) { + /* line 229, ../sass/bootstrap/_navbar.scss */ + .navbar-nav { + float: left; + margin: 0; + } + /* line 267, ../sass/bootstrap/_navbar.scss */ + .navbar-nav > li { + float: left; + } + /* line 269, ../sass/bootstrap/_navbar.scss */ + .navbar-nav > li > a { + padding-top: 15px; + padding-bottom: 15px; + } + /* line 275, ../sass/bootstrap/_navbar.scss */ + .navbar-nav.navbar-right:last-child { + margin-right: -15px; + } +} + +@media (min-width: 768px) { + /* line 289, ../sass/bootstrap/_navbar.scss */ + .navbar-left { + float: left !important; + } + + /* line 292, ../sass/bootstrap/_navbar.scss */ + .navbar-right { + float: right !important; + } +} +/* line 303, ../sass/bootstrap/_navbar.scss */ +.navbar-form { + margin-left: -15px; + margin-right: -15px; + padding: 10px 15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + margin-top: 8px; + margin-bottom: 8px; +} +@media (max-width: 767px) { + /* line 315, ../sass/bootstrap/_navbar.scss */ + .navbar-form .form-group { + margin-bottom: 5px; + } +} +@media (min-width: 768px) { + /* line 303, ../sass/bootstrap/_navbar.scss */ + .navbar-form { + width: auto; + border: 0; + margin-left: 0; + margin-right: 0; + padding-top: 0; + padding-bottom: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + /* line 335, ../sass/bootstrap/_navbar.scss */ + .navbar-form.navbar-right:last-child { + margin-right: -15px; + } +} + +/* line 345, ../sass/bootstrap/_navbar.scss */ +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-right-radius: 0; + border-top-left-radius: 0; +} + +/* line 350, ../sass/bootstrap/_navbar.scss */ +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +/* line 359, ../sass/bootstrap/_navbar.scss */ +.navbar-btn { + margin-top: 8px; + margin-bottom: 8px; +} +/* line 362, ../sass/bootstrap/_navbar.scss */ +.navbar-btn.btn-sm, .btn-group-sm > .navbar-btn.btn { + margin-top: 10px; + margin-bottom: 10px; +} +/* line 365, ../sass/bootstrap/_navbar.scss */ +.navbar-btn.btn-xs, .btn-group-xs > .navbar-btn.btn { + margin-top: 14px; + margin-bottom: 14px; +} + +/* line 375, ../sass/bootstrap/_navbar.scss */ +.navbar-text { + margin-top: 15px; + margin-bottom: 15px; +} +@media (min-width: 768px) { + /* line 375, ../sass/bootstrap/_navbar.scss */ + .navbar-text { + float: left; + margin-left: 15px; + margin-right: 15px; + } + /* line 384, ../sass/bootstrap/_navbar.scss */ + .navbar-text.navbar-right:last-child { + margin-right: 0; + } +} + +/* line 394, ../sass/bootstrap/_navbar.scss */ +.navbar-default { + background-color: #f8f8f8; + border-color: #e7e7e7; +} +/* line 398, ../sass/bootstrap/_navbar.scss */ +.navbar-default .navbar-brand { + color: #777; +} +/* line 400, ../sass/bootstrap/_navbar.scss */ +.navbar-default .navbar-brand:hover, .navbar-default .navbar-brand:focus { + color: #5e5e5e; + background-color: transparent; +} +/* line 407, ../sass/bootstrap/_navbar.scss */ +.navbar-default .navbar-text { + color: #777; +} +/* line 412, ../sass/bootstrap/_navbar.scss */ +.navbar-default .navbar-nav > li > a { + color: #777; +} +/* line 415, ../sass/bootstrap/_navbar.scss */ +.navbar-default .navbar-nav > li > a:hover, .navbar-default .navbar-nav > li > a:focus { + color: #333; + background-color: transparent; +} +/* line 422, ../sass/bootstrap/_navbar.scss */ +.navbar-default .navbar-nav > .active > a, .navbar-default .navbar-nav > .active > a:hover, .navbar-default .navbar-nav > .active > a:focus { + color: #555; + background-color: #e7e7e7; +} +/* line 430, ../sass/bootstrap/_navbar.scss */ +.navbar-default .navbar-nav > .disabled > a, .navbar-default .navbar-nav > .disabled > a:hover, .navbar-default .navbar-nav > .disabled > a:focus { + color: #ccc; + background-color: transparent; +} +/* line 439, ../sass/bootstrap/_navbar.scss */ +.navbar-default .navbar-toggle { + border-color: #ddd; +} +/* line 441, ../sass/bootstrap/_navbar.scss */ +.navbar-default .navbar-toggle:hover, .navbar-default .navbar-toggle:focus { + background-color: #ddd; +} +/* line 445, ../sass/bootstrap/_navbar.scss */ +.navbar-default .navbar-toggle .icon-bar { + background-color: #888; +} +/* line 450, ../sass/bootstrap/_navbar.scss */ +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #e7e7e7; +} +/* line 459, ../sass/bootstrap/_navbar.scss */ +.navbar-default .navbar-nav > .open > a, .navbar-default .navbar-nav > .open > a:hover, .navbar-default .navbar-nav > .open > a:focus { + background-color: #e7e7e7; + color: #555; +} +@media (max-width: 767px) { + /* line 470, ../sass/bootstrap/_navbar.scss */ + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #777; + } + /* line 472, ../sass/bootstrap/_navbar.scss */ + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333; + background-color: transparent; + } + /* line 479, ../sass/bootstrap/_navbar.scss */ + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #555; + background-color: #e7e7e7; + } + /* line 487, ../sass/bootstrap/_navbar.scss */ + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #ccc; + background-color: transparent; + } +} +/* line 503, ../sass/bootstrap/_navbar.scss */ +.navbar-default .navbar-link { + color: #777; +} +/* line 505, ../sass/bootstrap/_navbar.scss */ +.navbar-default .navbar-link:hover { + color: #333; +} +/* line 510, ../sass/bootstrap/_navbar.scss */ +.navbar-default .btn-link { + color: #777; +} +/* line 512, ../sass/bootstrap/_navbar.scss */ +.navbar-default .btn-link:hover, .navbar-default .btn-link:focus { + color: #333; +} +/* line 518, ../sass/bootstrap/_navbar.scss */ +.navbar-default .btn-link[disabled]:hover, .navbar-default .btn-link[disabled]:focus, fieldset[disabled] .navbar-default .btn-link:hover, fieldset[disabled] .navbar-default .btn-link:focus { + color: #ccc; +} + +/* line 528, ../sass/bootstrap/_navbar.scss */ +.navbar-inverse { + background-color: #222; + border-color: #090909; +} +/* line 532, ../sass/bootstrap/_navbar.scss */ +.navbar-inverse .navbar-brand { + color: #777777; +} +/* line 534, ../sass/bootstrap/_navbar.scss */ +.navbar-inverse .navbar-brand:hover, .navbar-inverse .navbar-brand:focus { + color: #fff; + background-color: transparent; +} +/* line 541, ../sass/bootstrap/_navbar.scss */ +.navbar-inverse .navbar-text { + color: #777777; +} +/* line 546, ../sass/bootstrap/_navbar.scss */ +.navbar-inverse .navbar-nav > li > a { + color: #777777; +} +/* line 549, ../sass/bootstrap/_navbar.scss */ +.navbar-inverse .navbar-nav > li > a:hover, .navbar-inverse .navbar-nav > li > a:focus { + color: #fff; + background-color: transparent; +} +/* line 556, ../sass/bootstrap/_navbar.scss */ +.navbar-inverse .navbar-nav > .active > a, .navbar-inverse .navbar-nav > .active > a:hover, .navbar-inverse .navbar-nav > .active > a:focus { + color: #fff; + background-color: #090909; +} +/* line 564, ../sass/bootstrap/_navbar.scss */ +.navbar-inverse .navbar-nav > .disabled > a, .navbar-inverse .navbar-nav > .disabled > a:hover, .navbar-inverse .navbar-nav > .disabled > a:focus { + color: #444; + background-color: transparent; +} +/* line 574, ../sass/bootstrap/_navbar.scss */ +.navbar-inverse .navbar-toggle { + border-color: #333; +} +/* line 576, ../sass/bootstrap/_navbar.scss */ +.navbar-inverse .navbar-toggle:hover, .navbar-inverse .navbar-toggle:focus { + background-color: #333; +} +/* line 580, ../sass/bootstrap/_navbar.scss */ +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #fff; +} +/* line 585, ../sass/bootstrap/_navbar.scss */ +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #101010; +} +/* line 593, ../sass/bootstrap/_navbar.scss */ +.navbar-inverse .navbar-nav > .open > a, .navbar-inverse .navbar-nav > .open > a:hover, .navbar-inverse .navbar-nav > .open > a:focus { + background-color: #090909; + color: #fff; +} +@media (max-width: 767px) { + /* line 604, ../sass/bootstrap/_navbar.scss */ + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #090909; + } + /* line 607, ../sass/bootstrap/_navbar.scss */ + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #090909; + } + /* line 610, ../sass/bootstrap/_navbar.scss */ + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #777777; + } + /* line 612, ../sass/bootstrap/_navbar.scss */ + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #fff; + background-color: transparent; + } + /* line 619, ../sass/bootstrap/_navbar.scss */ + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #fff; + background-color: #090909; + } + /* line 627, ../sass/bootstrap/_navbar.scss */ + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444; + background-color: transparent; + } +} +/* line 638, ../sass/bootstrap/_navbar.scss */ +.navbar-inverse .navbar-link { + color: #777777; +} +/* line 640, ../sass/bootstrap/_navbar.scss */ +.navbar-inverse .navbar-link:hover { + color: #fff; +} +/* line 645, ../sass/bootstrap/_navbar.scss */ +.navbar-inverse .btn-link { + color: #777777; +} +/* line 647, ../sass/bootstrap/_navbar.scss */ +.navbar-inverse .btn-link:hover, .navbar-inverse .btn-link:focus { + color: #fff; +} +/* line 653, ../sass/bootstrap/_navbar.scss */ +.navbar-inverse .btn-link[disabled]:hover, .navbar-inverse .btn-link[disabled]:focus, fieldset[disabled] .navbar-inverse .btn-link:hover, fieldset[disabled] .navbar-inverse .btn-link:focus { + color: #444; +} + +/* line 6, ../sass/bootstrap/_breadcrumbs.scss */ +.breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: #f5f5f5; + border-radius: 4px; +} +/* line 13, ../sass/bootstrap/_breadcrumbs.scss */ +.breadcrumb > li { + display: inline-block; +} +/* line 16, ../sass/bootstrap/_breadcrumbs.scss */ +.breadcrumb > li + li:before { + content: "/ "; + padding: 0 5px; + color: #ccc; +} +/* line 23, ../sass/bootstrap/_breadcrumbs.scss */ +.breadcrumb > .active { + color: #777777; +} + +/* line 4, ../sass/bootstrap/_pagination.scss */ +.pagination { + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px; +} +/* line 10, ../sass/bootstrap/_pagination.scss */ +.pagination > li { + display: inline; +} +/* line 12, ../sass/bootstrap/_pagination.scss */ +.pagination > li > a, +.pagination > li > span { + position: relative; + float: left; + padding: 6px 12px; + line-height: 1.42857; + text-decoration: none; + color: #428bca; + background-color: #fff; + border: 1px solid #ddd; + margin-left: -1px; +} +/* line 25, ../sass/bootstrap/_pagination.scss */ +.pagination > li:first-child > a, +.pagination > li:first-child > span { + margin-left: 0; + border-bottom-left-radius: 4px; + border-top-left-radius: 4px; +} +/* line 32, ../sass/bootstrap/_pagination.scss */ +.pagination > li:last-child > a, +.pagination > li:last-child > span { + border-bottom-right-radius: 4px; + border-top-right-radius: 4px; +} +/* line 41, ../sass/bootstrap/_pagination.scss */ +.pagination > li > a:hover, .pagination > li > a:focus, +.pagination > li > span:hover, +.pagination > li > span:focus { + color: #2a6496; + background-color: #eeeeee; + border-color: #ddd; +} +/* line 51, ../sass/bootstrap/_pagination.scss */ +.pagination > .active > a, .pagination > .active > a:hover, .pagination > .active > a:focus, +.pagination > .active > span, +.pagination > .active > span:hover, +.pagination > .active > span:focus { + z-index: 2; + color: #fff; + background-color: #428bca; + border-color: #428bca; + cursor: default; +} +/* line 63, ../sass/bootstrap/_pagination.scss */ +.pagination > .disabled > span, +.pagination > .disabled > span:hover, +.pagination > .disabled > span:focus, +.pagination > .disabled > a, +.pagination > .disabled > a:hover, +.pagination > .disabled > a:focus { + color: #777777; + background-color: #fff; + border-color: #ddd; + cursor: not-allowed; +} + +/* line 5, ../sass/bootstrap/mixins/_pagination.scss */ +.pagination-lg > li > a, +.pagination-lg > li > span { + padding: 10px 16px; + font-size: 18px; +} +/* line 11, ../sass/bootstrap/mixins/_pagination.scss */ +.pagination-lg > li:first-child > a, +.pagination-lg > li:first-child > span { + border-bottom-left-radius: 6px; + border-top-left-radius: 6px; +} +/* line 17, ../sass/bootstrap/mixins/_pagination.scss */ +.pagination-lg > li:last-child > a, +.pagination-lg > li:last-child > span { + border-bottom-right-radius: 6px; + border-top-right-radius: 6px; +} + +/* line 5, ../sass/bootstrap/mixins/_pagination.scss */ +.pagination-sm > li > a, +.pagination-sm > li > span { + padding: 5px 10px; + font-size: 12px; +} +/* line 11, ../sass/bootstrap/mixins/_pagination.scss */ +.pagination-sm > li:first-child > a, +.pagination-sm > li:first-child > span { + border-bottom-left-radius: 3px; + border-top-left-radius: 3px; +} +/* line 17, ../sass/bootstrap/mixins/_pagination.scss */ +.pagination-sm > li:last-child > a, +.pagination-sm > li:last-child > span { + border-bottom-right-radius: 3px; + border-top-right-radius: 3px; +} + +/* line 6, ../sass/bootstrap/_pager.scss */ +.pager { + padding-left: 0; + margin: 20px 0; + list-style: none; + text-align: center; +} +/* line 14, ../sass/bootstrap/mixins/_clearfix.scss */ +.pager:before, .pager:after { + content: " "; + display: table; +} +/* line 19, ../sass/bootstrap/mixins/_clearfix.scss */ +.pager:after { + clear: both; +} +/* line 12, ../sass/bootstrap/_pager.scss */ +.pager li { + display: inline; +} +/* line 14, ../sass/bootstrap/_pager.scss */ +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 15px; +} +/* line 23, ../sass/bootstrap/_pager.scss */ +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} +/* line 31, ../sass/bootstrap/_pager.scss */ +.pager .next > a, +.pager .next > span { + float: right; +} +/* line 38, ../sass/bootstrap/_pager.scss */ +.pager .previous > a, +.pager .previous > span { + float: left; +} +/* line 45, ../sass/bootstrap/_pager.scss */ +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #777777; + background-color: #fff; + cursor: not-allowed; +} + +/* line 5, ../sass/bootstrap/_labels.scss */ +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} +/* line 20, ../sass/bootstrap/_labels.scss */ +.label:empty { + display: none; +} +/* line 25, ../sass/bootstrap/_labels.scss */ +.btn .label { + position: relative; + top: -1px; +} + +/* line 33, ../sass/bootstrap/_labels.scss */ +a.label:hover, a.label:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} + +/* line 44, ../sass/bootstrap/_labels.scss */ +.label-default { + background-color: #777777; +} +/* line 7, ../sass/bootstrap/mixins/_labels.scss */ +.label-default[href]:hover, .label-default[href]:focus { + background-color: #5e5e5e; +} + +/* line 48, ../sass/bootstrap/_labels.scss */ +.label-primary { + background-color: #428bca; +} +/* line 7, ../sass/bootstrap/mixins/_labels.scss */ +.label-primary[href]:hover, .label-primary[href]:focus { + background-color: #3071a9; +} + +/* line 52, ../sass/bootstrap/_labels.scss */ +.label-success { + background-color: #5cb85c; +} +/* line 7, ../sass/bootstrap/mixins/_labels.scss */ +.label-success[href]:hover, .label-success[href]:focus { + background-color: #449d44; +} + +/* line 56, ../sass/bootstrap/_labels.scss */ +.label-info { + background-color: #5bc0de; +} +/* line 7, ../sass/bootstrap/mixins/_labels.scss */ +.label-info[href]:hover, .label-info[href]:focus { + background-color: #31b0d5; +} + +/* line 60, ../sass/bootstrap/_labels.scss */ +.label-warning { + background-color: #f0ad4e; +} +/* line 7, ../sass/bootstrap/mixins/_labels.scss */ +.label-warning[href]:hover, .label-warning[href]:focus { + background-color: #ec971f; +} + +/* line 64, ../sass/bootstrap/_labels.scss */ +.label-danger { + background-color: #d9534f; +} +/* line 7, ../sass/bootstrap/mixins/_labels.scss */ +.label-danger[href]:hover, .label-danger[href]:focus { + background-color: #c9302c; +} + +/* line 7, ../sass/bootstrap/_badges.scss */ +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + color: #fff; + line-height: 1; + vertical-align: baseline; + white-space: nowrap; + text-align: center; + background-color: #777777; + border-radius: 10px; +} +/* line 22, ../sass/bootstrap/_badges.scss */ +.badge:empty { + display: none; +} +/* line 27, ../sass/bootstrap/_badges.scss */ +.btn .badge { + position: relative; + top: -1px; +} +/* line 31, ../sass/bootstrap/_badges.scss */ +.btn-xs .badge, .btn-group-xs > .btn .badge { + top: 0; + padding: 1px 5px; +} +/* line 39, ../sass/bootstrap/_badges.scss */ +a.list-group-item.active > .badge, .nav-pills > .active > a > .badge { + color: #428bca; + background-color: #fff; +} +/* line 44, ../sass/bootstrap/_badges.scss */ +.nav-pills > li > a > .badge { + margin-left: 3px; +} + +/* line 51, ../sass/bootstrap/_badges.scss */ +a.badge:hover, a.badge:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} + +/* line 6, ../sass/bootstrap/_jumbotron.scss */ +.jumbotron { + padding: 30px; + margin-bottom: 30px; + color: inherit; + background-color: #eeeeee; +} +/* line 12, ../sass/bootstrap/_jumbotron.scss */ +.jumbotron h1, +.jumbotron .h1 { + color: inherit; +} +/* line 16, ../sass/bootstrap/_jumbotron.scss */ +.jumbotron p { + margin-bottom: 15px; + font-size: 21px; + font-weight: 200; +} +/* line 22, ../sass/bootstrap/_jumbotron.scss */ +.jumbotron > hr { + border-top-color: #d5d5d5; +} +/* line 26, ../sass/bootstrap/_jumbotron.scss */ +.container .jumbotron { + border-radius: 6px; +} +/* line 30, ../sass/bootstrap/_jumbotron.scss */ +.jumbotron .container { + max-width: 100%; +} +@media screen and (min-width: 768px) { + /* line 6, ../sass/bootstrap/_jumbotron.scss */ + .jumbotron { + padding-top: 48px; + padding-bottom: 48px; + } + /* line 38, ../sass/bootstrap/_jumbotron.scss */ + .container .jumbotron { + padding-left: 60px; + padding-right: 60px; + } + /* line 43, ../sass/bootstrap/_jumbotron.scss */ + .jumbotron h1, + .jumbotron .h1 { + font-size: 63px; + } +} + +/* line 7, ../sass/bootstrap/_thumbnails.scss */ +.thumbnail { + display: block; + padding: 4px; + margin-bottom: 20px; + line-height: 1.42857; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; +} +/* line 17, ../sass/bootstrap/_thumbnails.scss */ +.thumbnail > img, +.thumbnail a > img { + display: block; + width: 100% \9; + max-width: 100%; + height: auto; + margin-left: auto; + margin-right: auto; +} +/* line 27, ../sass/bootstrap/_thumbnails.scss */ +.thumbnail .caption { + padding: 9px; + color: #333333; +} + +/* line 34, ../sass/bootstrap/_thumbnails.scss */ +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #428bca; +} + +/* line 9, ../sass/bootstrap/_alerts.scss */ +.alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} +/* line 16, ../sass/bootstrap/_alerts.scss */ +.alert h4 { + margin-top: 0; + color: inherit; +} +/* line 22, ../sass/bootstrap/_alerts.scss */ +.alert .alert-link { + font-weight: bold; +} +/* line 27, ../sass/bootstrap/_alerts.scss */ +.alert > p, +.alert > ul { + margin-bottom: 0; +} +/* line 31, ../sass/bootstrap/_alerts.scss */ +.alert > p + p { + margin-top: 5px; +} + +/* line 40, ../sass/bootstrap/_alerts.scss */ +.alert-dismissable, +.alert-dismissible { + padding-right: 35px; +} +/* line 45, ../sass/bootstrap/_alerts.scss */ +.alert-dismissable .close, +.alert-dismissible .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; +} + +/* line 57, ../sass/bootstrap/_alerts.scss */ +.alert-success { + background-color: #dff0d8; + border-color: #d6e9c6; + color: #3c763d; +} +/* line 8, ../sass/bootstrap/mixins/_alerts.scss */ +.alert-success hr { + border-top-color: #c9e2b3; +} +/* line 11, ../sass/bootstrap/mixins/_alerts.scss */ +.alert-success .alert-link { + color: #2b542c; +} + +/* line 60, ../sass/bootstrap/_alerts.scss */ +.alert-info { + background-color: #d9edf7; + border-color: #bce8f1; + color: #31708f; +} +/* line 8, ../sass/bootstrap/mixins/_alerts.scss */ +.alert-info hr { + border-top-color: #a6e1ec; +} +/* line 11, ../sass/bootstrap/mixins/_alerts.scss */ +.alert-info .alert-link { + color: #245269; +} + +/* line 63, ../sass/bootstrap/_alerts.scss */ +.alert-warning { + background-color: #fcf8e3; + border-color: #faebcc; + color: #8a6d3b; +} +/* line 8, ../sass/bootstrap/mixins/_alerts.scss */ +.alert-warning hr { + border-top-color: #f7e1b5; +} +/* line 11, ../sass/bootstrap/mixins/_alerts.scss */ +.alert-warning .alert-link { + color: #66512c; +} + +/* line 66, ../sass/bootstrap/_alerts.scss */ +.alert-danger { + background-color: #f2dede; + border-color: #ebccd1; + color: #a94442; +} +/* line 8, ../sass/bootstrap/mixins/_alerts.scss */ +.alert-danger hr { + border-top-color: #e4b9c0; +} +/* line 11, ../sass/bootstrap/mixins/_alerts.scss */ +.alert-danger .alert-link { + color: #843534; +} + +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +/* line 27, ../sass/bootstrap/_progress-bars.scss */ +.progress { + overflow: hidden; + height: 20px; + margin-bottom: 20px; + background-color: #f5f5f5; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} + +/* line 37, ../sass/bootstrap/_progress-bars.scss */ +.progress-bar { + float: left; + width: 0%; + height: 100%; + font-size: 12px; + line-height: 20px; + color: #fff; + text-align: center; + background-color: #428bca; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-transition: width 0.6s ease; + -o-transition: width 0.6s ease; + transition: width 0.6s ease; +} + +/* line 55, ../sass/bootstrap/_progress-bars.scss */ +.progress-striped .progress-bar, +.progress-bar-striped { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-size: 40px 40px; +} + +/* line 65, ../sass/bootstrap/_progress-bars.scss */ +.progress.active .progress-bar, +.progress-bar.active { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} + +/* line 72, ../sass/bootstrap/_progress-bars.scss */ +.progress-bar[aria-valuenow="1"], .progress-bar[aria-valuenow="2"] { + min-width: 30px; +} +/* line 77, ../sass/bootstrap/_progress-bars.scss */ +.progress-bar[aria-valuenow="0"] { + color: #777777; + min-width: 30px; + background-color: transparent; + background-image: none; + box-shadow: none; +} + +/* line 91, ../sass/bootstrap/_progress-bars.scss */ +.progress-bar-success { + background-color: #5cb85c; +} +/* line 7, ../sass/bootstrap/mixins/_progress-bar.scss */ +.progress-striped .progress-bar-success { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +/* line 95, ../sass/bootstrap/_progress-bars.scss */ +.progress-bar-info { + background-color: #5bc0de; +} +/* line 7, ../sass/bootstrap/mixins/_progress-bar.scss */ +.progress-striped .progress-bar-info { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +/* line 99, ../sass/bootstrap/_progress-bars.scss */ +.progress-bar-warning { + background-color: #f0ad4e; +} +/* line 7, ../sass/bootstrap/mixins/_progress-bar.scss */ +.progress-striped .progress-bar-warning { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +/* line 103, ../sass/bootstrap/_progress-bars.scss */ +.progress-bar-danger { + background-color: #d9534f; +} +/* line 7, ../sass/bootstrap/mixins/_progress-bar.scss */ +.progress-striped .progress-bar-danger { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +/* line 10, ../sass/bootstrap/_media.scss */ +.media, +.media-body { + overflow: hidden; + zoom: 1; +} + +/* line 17, ../sass/bootstrap/_media.scss */ +.media, +.media .media { + margin-top: 15px; +} + +/* line 21, ../sass/bootstrap/_media.scss */ +.media:first-child { + margin-top: 0; +} + +/* line 26, ../sass/bootstrap/_media.scss */ +.media-object { + display: block; +} + +/* line 31, ../sass/bootstrap/_media.scss */ +.media-heading { + margin: 0 0 5px; +} + +/* line 40, ../sass/bootstrap/_media.scss */ +.media > .pull-left { + margin-right: 10px; +} +/* line 43, ../sass/bootstrap/_media.scss */ +.media > .pull-right { + margin-left: 10px; +} + +/* line 53, ../sass/bootstrap/_media.scss */ +.media-list { + padding-left: 0; + list-style: none; +} + +/* line 10, ../sass/bootstrap/_list-group.scss */ +.list-group { + margin-bottom: 20px; + padding-left: 0; +} + +/* line 21, ../sass/bootstrap/_list-group.scss */ +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #fff; + border: 1px solid #ddd; +} +/* line 31, ../sass/bootstrap/_list-group.scss */ +.list-group-item:first-child { + border-top-right-radius: 4px; + border-top-left-radius: 4px; +} +/* line 34, ../sass/bootstrap/_list-group.scss */ +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +/* line 40, ../sass/bootstrap/_list-group.scss */ +.list-group-item > .badge { + float: right; +} +/* line 43, ../sass/bootstrap/_list-group.scss */ +.list-group-item > .badge + .badge { + margin-right: 5px; +} + +/* line 54, ../sass/bootstrap/_list-group.scss */ +a.list-group-item { + color: #555; +} +/* line 57, ../sass/bootstrap/_list-group.scss */ +a.list-group-item .list-group-item-heading { + color: #333; +} +/* line 62, ../sass/bootstrap/_list-group.scss */ +a.list-group-item:hover, a.list-group-item:focus { + text-decoration: none; + color: #555; + background-color: #f5f5f5; +} + +/* line 72, ../sass/bootstrap/_list-group.scss */ +.list-group-item.disabled, .list-group-item.disabled:hover, .list-group-item.disabled:focus { + background-color: #eeeeee; + color: #777777; +} +/* line 79, ../sass/bootstrap/_list-group.scss */ +.list-group-item.disabled .list-group-item-heading, .list-group-item.disabled:hover .list-group-item-heading, .list-group-item.disabled:focus .list-group-item-heading { + color: inherit; +} +/* line 82, ../sass/bootstrap/_list-group.scss */ +.list-group-item.disabled .list-group-item-text, .list-group-item.disabled:hover .list-group-item-text, .list-group-item.disabled:focus .list-group-item-text { + color: #777777; +} +/* line 88, ../sass/bootstrap/_list-group.scss */ +.list-group-item.active, .list-group-item.active:hover, .list-group-item.active:focus { + z-index: 2; + color: #fff; + background-color: #428bca; + border-color: #428bca; +} +/* line 97, ../sass/bootstrap/_list-group.scss */ +.list-group-item.active .list-group-item-heading, +.list-group-item.active .list-group-item-heading > small, +.list-group-item.active .list-group-item-heading > .small, .list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading > small, +.list-group-item.active:hover .list-group-item-heading > .small, .list-group-item.active:focus .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading > small, +.list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; +} +/* line 102, ../sass/bootstrap/_list-group.scss */ +.list-group-item.active .list-group-item-text, .list-group-item.active:hover .list-group-item-text, .list-group-item.active:focus .list-group-item-text { + color: #e1edf7; +} + +/* line 4, ../sass/bootstrap/mixins/_list-group.scss */ +.list-group-item-success { + color: #3c763d; + background-color: #dff0d8; +} + +/* line 11, ../sass/bootstrap/mixins/_list-group.scss */ +a.list-group-item-success { + color: #3c763d; +} +/* line 14, ../sass/bootstrap/mixins/_list-group.scss */ +a.list-group-item-success .list-group-item-heading { + color: inherit; +} +/* line 18, ../sass/bootstrap/mixins/_list-group.scss */ +a.list-group-item-success:hover, a.list-group-item-success:focus { + color: #3c763d; + background-color: #d0e9c6; +} +/* line 23, ../sass/bootstrap/mixins/_list-group.scss */ +a.list-group-item-success.active, a.list-group-item-success.active:hover, a.list-group-item-success.active:focus { + color: #fff; + background-color: #3c763d; + border-color: #3c763d; +} + +/* line 4, ../sass/bootstrap/mixins/_list-group.scss */ +.list-group-item-info { + color: #31708f; + background-color: #d9edf7; +} + +/* line 11, ../sass/bootstrap/mixins/_list-group.scss */ +a.list-group-item-info { + color: #31708f; +} +/* line 14, ../sass/bootstrap/mixins/_list-group.scss */ +a.list-group-item-info .list-group-item-heading { + color: inherit; +} +/* line 18, ../sass/bootstrap/mixins/_list-group.scss */ +a.list-group-item-info:hover, a.list-group-item-info:focus { + color: #31708f; + background-color: #c4e3f3; +} +/* line 23, ../sass/bootstrap/mixins/_list-group.scss */ +a.list-group-item-info.active, a.list-group-item-info.active:hover, a.list-group-item-info.active:focus { + color: #fff; + background-color: #31708f; + border-color: #31708f; +} + +/* line 4, ../sass/bootstrap/mixins/_list-group.scss */ +.list-group-item-warning { + color: #8a6d3b; + background-color: #fcf8e3; +} + +/* line 11, ../sass/bootstrap/mixins/_list-group.scss */ +a.list-group-item-warning { + color: #8a6d3b; +} +/* line 14, ../sass/bootstrap/mixins/_list-group.scss */ +a.list-group-item-warning .list-group-item-heading { + color: inherit; +} +/* line 18, ../sass/bootstrap/mixins/_list-group.scss */ +a.list-group-item-warning:hover, a.list-group-item-warning:focus { + color: #8a6d3b; + background-color: #faf2cc; +} +/* line 23, ../sass/bootstrap/mixins/_list-group.scss */ +a.list-group-item-warning.active, a.list-group-item-warning.active:hover, a.list-group-item-warning.active:focus { + color: #fff; + background-color: #8a6d3b; + border-color: #8a6d3b; +} + +/* line 4, ../sass/bootstrap/mixins/_list-group.scss */ +.list-group-item-danger { + color: #a94442; + background-color: #f2dede; +} + +/* line 11, ../sass/bootstrap/mixins/_list-group.scss */ +a.list-group-item-danger { + color: #a94442; +} +/* line 14, ../sass/bootstrap/mixins/_list-group.scss */ +a.list-group-item-danger .list-group-item-heading { + color: inherit; +} +/* line 18, ../sass/bootstrap/mixins/_list-group.scss */ +a.list-group-item-danger:hover, a.list-group-item-danger:focus { + color: #a94442; + background-color: #ebcccc; +} +/* line 23, ../sass/bootstrap/mixins/_list-group.scss */ +a.list-group-item-danger.active, a.list-group-item-danger.active:hover, a.list-group-item-danger.active:focus { + color: #fff; + background-color: #a94442; + border-color: #a94442; +} + +/* line 124, ../sass/bootstrap/_list-group.scss */ +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} + +/* line 128, ../sass/bootstrap/_list-group.scss */ +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} + +/* line 7, ../sass/bootstrap/_panels.scss */ +.panel { + margin-bottom: 20px; + background-color: #fff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); +} + +/* line 16, ../sass/bootstrap/_panels.scss */ +.panel-body { + padding: 15px; +} +/* line 14, ../sass/bootstrap/mixins/_clearfix.scss */ +.panel-body:before, .panel-body:after { + content: " "; + display: table; +} +/* line 19, ../sass/bootstrap/mixins/_clearfix.scss */ +.panel-body:after { + clear: both; +} + +/* line 22, ../sass/bootstrap/_panels.scss */ +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +/* line 27, ../sass/bootstrap/_panels.scss */ +.panel-heading > .dropdown .dropdown-toggle { + color: inherit; +} + +/* line 33, ../sass/bootstrap/_panels.scss */ +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit; +} +/* line 39, ../sass/bootstrap/_panels.scss */ +.panel-title > a { + color: inherit; +} + +/* line 45, ../sass/bootstrap/_panels.scss */ +.panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} + +/* line 59, ../sass/bootstrap/_panels.scss */ +.panel > .list-group { + margin-bottom: 0; +} +/* line 62, ../sass/bootstrap/_panels.scss */ +.panel > .list-group .list-group-item { + border-width: 1px 0; + border-radius: 0; +} +/* line 69, ../sass/bootstrap/_panels.scss */ +.panel > .list-group:first-child .list-group-item:first-child { + border-top: 0; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +/* line 76, ../sass/bootstrap/_panels.scss */ +.panel > .list-group:last-child .list-group-item:last-child { + border-bottom: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} + +/* line 85, ../sass/bootstrap/_panels.scss */ +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} + +/* line 89, ../sass/bootstrap/_panels.scss */ +.list-group + .panel-footer { + border-top-width: 0; +} + +/* line 99, ../sass/bootstrap/_panels.scss */ +.panel > .table, +.panel > .table-responsive > .table, +.panel > .panel-collapse > .table { + margin-bottom: 0; +} +/* line 105, ../sass/bootstrap/_panels.scss */ +.panel > .table:first-child, +.panel > .table-responsive:first-child > .table:first-child { + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +/* line 112, ../sass/bootstrap/_panels.scss */ +.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { + border-top-left-radius: 3px; +} +/* line 116, ../sass/bootstrap/_panels.scss */ +.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { + border-top-right-radius: 3px; +} +/* line 124, ../sass/bootstrap/_panels.scss */ +.panel > .table:last-child, +.panel > .table-responsive:last-child > .table:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +/* line 131, ../sass/bootstrap/_panels.scss */ +.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { + border-bottom-left-radius: 3px; +} +/* line 135, ../sass/bootstrap/_panels.scss */ +.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { + border-bottom-right-radius: 3px; +} +/* line 142, ../sass/bootstrap/_panels.scss */ +.panel > .panel-body + .table, +.panel > .panel-body + .table-responsive { + border-top: 1px solid #ddd; +} +/* line 146, ../sass/bootstrap/_panels.scss */ +.panel > .table > tbody:first-child > tr:first-child th, +.panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; +} +/* line 150, ../sass/bootstrap/_panels.scss */ +.panel > .table-bordered, +.panel > .table-responsive > .table-bordered { + border: 0; +} +/* line 157, ../sass/bootstrap/_panels.scss */ +.panel > .table-bordered > thead > tr > th:first-child, +.panel > .table-bordered > thead > tr > td:first-child, +.panel > .table-bordered > tbody > tr > th:first-child, +.panel > .table-bordered > tbody > tr > td:first-child, +.panel > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-bordered > tfoot > tr > td:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; +} +/* line 161, ../sass/bootstrap/_panels.scss */ +.panel > .table-bordered > thead > tr > th:last-child, +.panel > .table-bordered > thead > tr > td:last-child, +.panel > .table-bordered > tbody > tr > th:last-child, +.panel > .table-bordered > tbody > tr > td:last-child, +.panel > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-bordered > tfoot > tr > td:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; +} +/* line 170, ../sass/bootstrap/_panels.scss */ +.panel > .table-bordered > thead > tr:first-child > td, +.panel > .table-bordered > thead > tr:first-child > th, +.panel > .table-bordered > tbody > tr:first-child > td, +.panel > .table-bordered > tbody > tr:first-child > th, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { + border-bottom: 0; +} +/* line 179, ../sass/bootstrap/_panels.scss */ +.panel > .table-bordered > tbody > tr:last-child > td, +.panel > .table-bordered > tbody > tr:last-child > th, +.panel > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-bordered > tfoot > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { + border-bottom: 0; +} +/* line 186, ../sass/bootstrap/_panels.scss */ +.panel > .table-responsive { + border: 0; + margin-bottom: 0; +} + +/* line 198, ../sass/bootstrap/_panels.scss */ +.panel-group { + margin-bottom: 20px; +} +/* line 202, ../sass/bootstrap/_panels.scss */ +.panel-group .panel { + margin-bottom: 0; + border-radius: 4px; +} +/* line 205, ../sass/bootstrap/_panels.scss */ +.panel-group .panel + .panel { + margin-top: 5px; +} +/* line 210, ../sass/bootstrap/_panels.scss */ +.panel-group .panel-heading { + border-bottom: 0; +} +/* line 212, ../sass/bootstrap/_panels.scss */ +.panel-group .panel-heading + .panel-collapse > .panel-body { + border-top: 1px solid #ddd; +} +/* line 216, ../sass/bootstrap/_panels.scss */ +.panel-group .panel-footer { + border-top: 0; +} +/* line 218, ../sass/bootstrap/_panels.scss */ +.panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #ddd; +} + +/* line 226, ../sass/bootstrap/_panels.scss */ +.panel-default { + border-color: #ddd; +} +/* line 6, ../sass/bootstrap/mixins/_panels.scss */ +.panel-default > .panel-heading { + color: #333333; + background-color: #f5f5f5; + border-color: #ddd; +} +/* line 11, ../sass/bootstrap/mixins/_panels.scss */ +.panel-default > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ddd; +} +/* line 14, ../sass/bootstrap/mixins/_panels.scss */ +.panel-default > .panel-heading .badge { + color: #f5f5f5; + background-color: #333333; +} +/* line 20, ../sass/bootstrap/mixins/_panels.scss */ +.panel-default > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ddd; +} + +/* line 229, ../sass/bootstrap/_panels.scss */ +.panel-primary { + border-color: #428bca; +} +/* line 6, ../sass/bootstrap/mixins/_panels.scss */ +.panel-primary > .panel-heading { + color: #fff; + background-color: #428bca; + border-color: #428bca; +} +/* line 11, ../sass/bootstrap/mixins/_panels.scss */ +.panel-primary > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #428bca; +} +/* line 14, ../sass/bootstrap/mixins/_panels.scss */ +.panel-primary > .panel-heading .badge { + color: #428bca; + background-color: #fff; +} +/* line 20, ../sass/bootstrap/mixins/_panels.scss */ +.panel-primary > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #428bca; +} + +/* line 232, ../sass/bootstrap/_panels.scss */ +.panel-success { + border-color: #d6e9c6; +} +/* line 6, ../sass/bootstrap/mixins/_panels.scss */ +.panel-success > .panel-heading { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +/* line 11, ../sass/bootstrap/mixins/_panels.scss */ +.panel-success > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #d6e9c6; +} +/* line 14, ../sass/bootstrap/mixins/_panels.scss */ +.panel-success > .panel-heading .badge { + color: #dff0d8; + background-color: #3c763d; +} +/* line 20, ../sass/bootstrap/mixins/_panels.scss */ +.panel-success > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #d6e9c6; +} + +/* line 235, ../sass/bootstrap/_panels.scss */ +.panel-info { + border-color: #bce8f1; +} +/* line 6, ../sass/bootstrap/mixins/_panels.scss */ +.panel-info > .panel-heading { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +/* line 11, ../sass/bootstrap/mixins/_panels.scss */ +.panel-info > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #bce8f1; +} +/* line 14, ../sass/bootstrap/mixins/_panels.scss */ +.panel-info > .panel-heading .badge { + color: #d9edf7; + background-color: #31708f; +} +/* line 20, ../sass/bootstrap/mixins/_panels.scss */ +.panel-info > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #bce8f1; +} + +/* line 238, ../sass/bootstrap/_panels.scss */ +.panel-warning { + border-color: #faebcc; +} +/* line 6, ../sass/bootstrap/mixins/_panels.scss */ +.panel-warning > .panel-heading { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +/* line 11, ../sass/bootstrap/mixins/_panels.scss */ +.panel-warning > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #faebcc; +} +/* line 14, ../sass/bootstrap/mixins/_panels.scss */ +.panel-warning > .panel-heading .badge { + color: #fcf8e3; + background-color: #8a6d3b; +} +/* line 20, ../sass/bootstrap/mixins/_panels.scss */ +.panel-warning > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #faebcc; +} + +/* line 241, ../sass/bootstrap/_panels.scss */ +.panel-danger { + border-color: #ebccd1; +} +/* line 6, ../sass/bootstrap/mixins/_panels.scss */ +.panel-danger > .panel-heading { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +/* line 11, ../sass/bootstrap/mixins/_panels.scss */ +.panel-danger > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ebccd1; +} +/* line 14, ../sass/bootstrap/mixins/_panels.scss */ +.panel-danger > .panel-heading .badge { + color: #f2dede; + background-color: #a94442; +} +/* line 20, ../sass/bootstrap/mixins/_panels.scss */ +.panel-danger > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ebccd1; +} + +/* line 5, ../sass/bootstrap/_responsive-embed.scss */ +.embed-responsive { + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; +} +/* line 12, ../sass/bootstrap/_responsive-embed.scss */ +.embed-responsive .embed-responsive-item, +.embed-responsive iframe, +.embed-responsive embed, +.embed-responsive object { + position: absolute; + top: 0; + left: 0; + bottom: 0; + height: 100%; + width: 100%; + border: 0; +} +/* line 26, ../sass/bootstrap/_responsive-embed.scss */ +.embed-responsive.embed-responsive-16by9 { + padding-bottom: 56.25%; +} +/* line 31, ../sass/bootstrap/_responsive-embed.scss */ +.embed-responsive.embed-responsive-4by3 { + padding-bottom: 75%; +} + +/* line 7, ../sass/bootstrap/_wells.scss */ +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} +/* line 15, ../sass/bootstrap/_wells.scss */ +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); +} + +/* line 22, ../sass/bootstrap/_wells.scss */ +.well-lg { + padding: 24px; + border-radius: 6px; +} + +/* line 26, ../sass/bootstrap/_wells.scss */ +.well-sm { + padding: 9px; + border-radius: 3px; +} + +/* line 6, ../sass/bootstrap/_close.scss */ +.close { + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + opacity: 0.2; + filter: alpha(opacity=20); +} +/* line 15, ../sass/bootstrap/_close.scss */ +.close:hover, .close:focus { + color: #000; + text-decoration: none; + cursor: pointer; + opacity: 0.5; + filter: alpha(opacity=50); +} + +/* line 29, ../sass/bootstrap/_close.scss */ +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} + +/* line 11, ../sass/bootstrap/_modals.scss */ +.modal-open { + overflow: hidden; +} + +/* line 16, ../sass/bootstrap/_modals.scss */ +.modal { + display: none; + overflow: hidden; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + -webkit-overflow-scrolling: touch; + outline: 0; +} +/* line 32, ../sass/bootstrap/_modals.scss */ +.modal.fade .modal-dialog { + -webkit-transform: translate3d(0, -25%, 0); + transform: translate3d(0, -25%, 0); + -webkit-transition: -webkit-transform 0.3s ease-out; + -moz-transition: -moz-transform 0.3s ease-out; + -o-transition: -o-transform 0.3s ease-out; + transition: transform 0.3s ease-out; +} +/* line 36, ../sass/bootstrap/_modals.scss */ +.modal.in .modal-dialog { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); +} + +/* line 38, ../sass/bootstrap/_modals.scss */ +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} + +/* line 44, ../sass/bootstrap/_modals.scss */ +.modal-dialog { + position: relative; + width: auto; + margin: 10px; +} + +/* line 51, ../sass/bootstrap/_modals.scss */ +.modal-content { + position: relative; + background-color: #fff; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + background-clip: padding-box; + outline: 0; +} + +/* line 64, ../sass/bootstrap/_modals.scss */ +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000; +} +/* line 73, ../sass/bootstrap/_modals.scss */ +.modal-backdrop.fade { + opacity: 0; + filter: alpha(opacity=0); +} +/* line 74, ../sass/bootstrap/_modals.scss */ +.modal-backdrop.in { + opacity: 0.5; + filter: alpha(opacity=50); +} + +/* line 79, ../sass/bootstrap/_modals.scss */ +.modal-header { + padding: 15px; + border-bottom: 1px solid #e5e5e5; + min-height: 16.42857px; +} + +/* line 85, ../sass/bootstrap/_modals.scss */ +.modal-header .close { + margin-top: -2px; +} + +/* line 90, ../sass/bootstrap/_modals.scss */ +.modal-title { + margin: 0; + line-height: 1.42857; +} + +/* line 97, ../sass/bootstrap/_modals.scss */ +.modal-body { + position: relative; + padding: 15px; +} + +/* line 103, ../sass/bootstrap/_modals.scss */ +.modal-footer { + padding: 15px; + text-align: right; + border-top: 1px solid #e5e5e5; +} +/* line 14, ../sass/bootstrap/mixins/_clearfix.scss */ +.modal-footer:before, .modal-footer:after { + content: " "; + display: table; +} +/* line 19, ../sass/bootstrap/mixins/_clearfix.scss */ +.modal-footer:after { + clear: both; +} +/* line 110, ../sass/bootstrap/_modals.scss */ +.modal-footer .btn + .btn { + margin-left: 5px; + margin-bottom: 0; +} +/* line 115, ../sass/bootstrap/_modals.scss */ +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +/* line 119, ../sass/bootstrap/_modals.scss */ +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} + +/* line 125, ../sass/bootstrap/_modals.scss */ +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} + +@media (min-width: 768px) { + /* line 136, ../sass/bootstrap/_modals.scss */ + .modal-dialog { + width: 600px; + margin: 30px auto; + } + + /* line 140, ../sass/bootstrap/_modals.scss */ + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + } + + /* line 145, ../sass/bootstrap/_modals.scss */ + .modal-sm { + width: 300px; + } +} +@media (min-width: 992px) { + /* line 149, ../sass/bootstrap/_modals.scss */ + .modal-lg { + width: 900px; + } +} +/* line 7, ../sass/bootstrap/_tooltip.scss */ +.tooltip { + position: absolute; + z-index: 1070; + display: block; + visibility: visible; + font-size: 12px; + line-height: 1.4; + opacity: 0; + filter: alpha(opacity=0); +} +/* line 16, ../sass/bootstrap/_tooltip.scss */ +.tooltip.in { + opacity: 0.9; + filter: alpha(opacity=90); +} +/* line 17, ../sass/bootstrap/_tooltip.scss */ +.tooltip.top { + margin-top: -3px; + padding: 5px 0; +} +/* line 18, ../sass/bootstrap/_tooltip.scss */ +.tooltip.right { + margin-left: 3px; + padding: 0 5px; +} +/* line 19, ../sass/bootstrap/_tooltip.scss */ +.tooltip.bottom { + margin-top: 3px; + padding: 5px 0; +} +/* line 20, ../sass/bootstrap/_tooltip.scss */ +.tooltip.left { + margin-left: -3px; + padding: 0 5px; +} + +/* line 24, ../sass/bootstrap/_tooltip.scss */ +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #fff; + text-align: center; + text-decoration: none; + background-color: #000; + border-radius: 4px; +} + +/* line 35, ../sass/bootstrap/_tooltip.scss */ +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} + +/* line 43, ../sass/bootstrap/_tooltip.scss */ +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +/* line 50, ../sass/bootstrap/_tooltip.scss */ +.tooltip.top-left .tooltip-arrow { + bottom: 0; + left: 5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +/* line 56, ../sass/bootstrap/_tooltip.scss */ +.tooltip.top-right .tooltip-arrow { + bottom: 0; + right: 5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +/* line 62, ../sass/bootstrap/_tooltip.scss */ +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000; +} +/* line 69, ../sass/bootstrap/_tooltip.scss */ +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000; +} +/* line 76, ../sass/bootstrap/_tooltip.scss */ +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +/* line 83, ../sass/bootstrap/_tooltip.scss */ +.tooltip.bottom-left .tooltip-arrow { + top: 0; + left: 5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +/* line 89, ../sass/bootstrap/_tooltip.scss */ +.tooltip.bottom-right .tooltip-arrow { + top: 0; + right: 5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} + +/* line 6, ../sass/bootstrap/_popovers.scss */ +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: none; + max-width: 276px; + padding: 1px; + text-align: left; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + white-space: normal; +} +/* line 26, ../sass/bootstrap/_popovers.scss */ +.popover.top { + margin-top: -10px; +} +/* line 27, ../sass/bootstrap/_popovers.scss */ +.popover.right { + margin-left: 10px; +} +/* line 28, ../sass/bootstrap/_popovers.scss */ +.popover.bottom { + margin-top: 10px; +} +/* line 29, ../sass/bootstrap/_popovers.scss */ +.popover.left { + margin-left: -10px; +} + +/* line 32, ../sass/bootstrap/_popovers.scss */ +.popover-title { + margin: 0; + padding: 8px 14px; + font-size: 14px; + font-weight: normal; + line-height: 18px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; +} + +/* line 43, ../sass/bootstrap/_popovers.scss */ +.popover-content { + padding: 9px 14px; +} + +/* line 52, ../sass/bootstrap/_popovers.scss */ +.popover > .arrow, .popover > .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} + +/* line 62, ../sass/bootstrap/_popovers.scss */ +.popover > .arrow { + border-width: 11px; +} + +/* line 65, ../sass/bootstrap/_popovers.scss */ +.popover > .arrow:after { + border-width: 10px; + content: ""; +} + +/* line 71, ../sass/bootstrap/_popovers.scss */ +.popover.top > .arrow { + left: 50%; + margin-left: -11px; + border-bottom-width: 0; + border-top-color: #999999; + border-top-color: rgba(0, 0, 0, 0.25); + bottom: -11px; +} +/* line 78, ../sass/bootstrap/_popovers.scss */ +.popover.top > .arrow:after { + content: " "; + bottom: 1px; + margin-left: -10px; + border-bottom-width: 0; + border-top-color: #fff; +} +/* line 86, ../sass/bootstrap/_popovers.scss */ +.popover.right > .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-left-width: 0; + border-right-color: #999999; + border-right-color: rgba(0, 0, 0, 0.25); +} +/* line 93, ../sass/bootstrap/_popovers.scss */ +.popover.right > .arrow:after { + content: " "; + left: 1px; + bottom: -10px; + border-left-width: 0; + border-right-color: #fff; +} +/* line 101, ../sass/bootstrap/_popovers.scss */ +.popover.bottom > .arrow { + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999999; + border-bottom-color: rgba(0, 0, 0, 0.25); + top: -11px; +} +/* line 108, ../sass/bootstrap/_popovers.scss */ +.popover.bottom > .arrow:after { + content: " "; + top: 1px; + margin-left: -10px; + border-top-width: 0; + border-bottom-color: #fff; +} +/* line 117, ../sass/bootstrap/_popovers.scss */ +.popover.left > .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999999; + border-left-color: rgba(0, 0, 0, 0.25); +} +/* line 124, ../sass/bootstrap/_popovers.scss */ +.popover.left > .arrow:after { + content: " "; + right: 1px; + border-right-width: 0; + border-left-color: #fff; + bottom: -10px; +} + +/* line 7, ../sass/bootstrap/_carousel.scss */ +.carousel { + position: relative; +} + +/* line 11, ../sass/bootstrap/_carousel.scss */ +.carousel-inner { + position: relative; + overflow: hidden; + width: 100%; +} +/* line 16, ../sass/bootstrap/_carousel.scss */ +.carousel-inner > .item { + display: none; + position: relative; + -webkit-transition: 0.6s ease-in-out left; + -o-transition: 0.6s ease-in-out left; + transition: 0.6s ease-in-out left; +} +/* line 22, ../sass/bootstrap/_carousel.scss */ +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + width: 100% \9; + max-width: 100%; + height: auto; + line-height: 1; +} +/* line 29, ../sass/bootstrap/_carousel.scss */ +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} +/* line 35, ../sass/bootstrap/_carousel.scss */ +.carousel-inner > .active { + left: 0; +} +/* line 39, ../sass/bootstrap/_carousel.scss */ +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} +/* line 46, ../sass/bootstrap/_carousel.scss */ +.carousel-inner > .next { + left: 100%; +} +/* line 49, ../sass/bootstrap/_carousel.scss */ +.carousel-inner > .prev { + left: -100%; +} +/* line 52, ../sass/bootstrap/_carousel.scss */ +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} +/* line 57, ../sass/bootstrap/_carousel.scss */ +.carousel-inner > .active.left { + left: -100%; +} +/* line 60, ../sass/bootstrap/_carousel.scss */ +.carousel-inner > .active.right { + left: 100%; +} + +/* line 69, ../sass/bootstrap/_carousel.scss */ +.carousel-control { + position: absolute; + top: 0; + left: 0; + bottom: 0; + width: 15%; + opacity: 0.5; + filter: alpha(opacity=50); + font-size: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); +} +/* line 84, ../sass/bootstrap/_carousel.scss */ +.carousel-control.left { + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); +} +/* line 87, ../sass/bootstrap/_carousel.scss */ +.carousel-control.right { + left: auto; + right: 0; + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); +} +/* line 94, ../sass/bootstrap/_carousel.scss */ +.carousel-control:hover, .carousel-control:focus { + outline: 0; + color: #fff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity=90); +} +/* line 103, ../sass/bootstrap/_carousel.scss */ +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + z-index: 5; + display: inline-block; +} +/* line 112, ../sass/bootstrap/_carousel.scss */ +.carousel-control .icon-prev, +.carousel-control .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; +} +/* line 117, ../sass/bootstrap/_carousel.scss */ +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; +} +/* line 122, ../sass/bootstrap/_carousel.scss */ +.carousel-control .icon-prev, +.carousel-control .icon-next { + width: 20px; + height: 20px; + margin-top: -10px; + font-family: serif; +} +/* line 132, ../sass/bootstrap/_carousel.scss */ +.carousel-control .icon-prev:before { + content: '\2039'; +} +/* line 137, ../sass/bootstrap/_carousel.scss */ +.carousel-control .icon-next:before { + content: '\203a'; +} + +/* line 148, ../sass/bootstrap/_carousel.scss */ +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + margin-left: -30%; + padding-left: 0; + list-style: none; + text-align: center; +} +/* line 159, ../sass/bootstrap/_carousel.scss */ +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + border: 1px solid #fff; + border-radius: 10px; + cursor: pointer; + background-color: #000 \9; + background-color: transparent; +} +/* line 180, ../sass/bootstrap/_carousel.scss */ +.carousel-indicators .active { + margin: 0; + width: 12px; + height: 12px; + background-color: #fff; +} + +/* line 191, ../sass/bootstrap/_carousel.scss */ +.carousel-caption { + position: absolute; + left: 15%; + right: 15%; + bottom: 20px; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); +} +/* line 202, ../sass/bootstrap/_carousel.scss */ +.carousel-caption .btn { + text-shadow: none; +} + +@media screen and (min-width: 768px) { + /* line 213, ../sass/bootstrap/_carousel.scss */ + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -15px; + font-size: 30px; + } + /* line 222, ../sass/bootstrap/_carousel.scss */ + .carousel-control .glyphicon-chevron-left, + .carousel-control .icon-prev { + margin-left: -15px; + } + /* line 226, ../sass/bootstrap/_carousel.scss */ + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-next { + margin-right: -15px; + } + + /* line 233, ../sass/bootstrap/_carousel.scss */ + .carousel-caption { + left: 20%; + right: 20%; + padding-bottom: 30px; + } + + /* line 240, ../sass/bootstrap/_carousel.scss */ + .carousel-indicators { + bottom: 20px; + } +} +/* line 14, ../sass/bootstrap/mixins/_clearfix.scss */ +.clearfix:before, .clearfix:after { + content: " "; + display: table; +} +/* line 19, ../sass/bootstrap/mixins/_clearfix.scss */ +.clearfix:after { + clear: both; +} + +/* line 12, ../sass/bootstrap/_utilities.scss */ +.center-block { + display: block; + margin-left: auto; + margin-right: auto; +} + +/* line 15, ../sass/bootstrap/_utilities.scss */ +.pull-right { + float: right !important; +} + +/* line 18, ../sass/bootstrap/_utilities.scss */ +.pull-left { + float: left !important; +} + +/* line 27, ../sass/bootstrap/_utilities.scss */ +.hide { + display: none !important; +} + +/* line 30, ../sass/bootstrap/_utilities.scss */ +.show { + display: block !important; +} + +/* line 33, ../sass/bootstrap/_utilities.scss */ +.invisible { + visibility: hidden; +} + +/* line 36, ../sass/bootstrap/_utilities.scss */ +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +/* line 45, ../sass/bootstrap/_utilities.scss */ +.hidden { + display: none !important; + visibility: hidden !important; +} + +/* line 54, ../sass/bootstrap/_utilities.scss */ +.affix { + position: fixed; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); +} + +@-ms-viewport { + width: device-width; +} +/* line 18, ../sass/bootstrap/mixins/_responsive-visibility.scss */ +.visible-xs, .visible-sm, .visible-md, .visible-lg { + display: none !important; +} + +/* line 31, ../sass/bootstrap/_responsive-utilities.scss */ +.visible-xs-block, +.visible-xs-inline, +.visible-xs-inline-block, +.visible-sm-block, +.visible-sm-inline, +.visible-sm-inline-block, +.visible-md-block, +.visible-md-inline, +.visible-md-inline-block, +.visible-lg-block, +.visible-lg-inline, +.visible-lg-inline-block { + display: none !important; +} + +@media (max-width: 767px) { + /* line 7, ../sass/bootstrap/mixins/_responsive-visibility.scss */ + .visible-xs { + display: block !important; + } + + /* line 10, ../sass/bootstrap/mixins/_responsive-visibility.scss */ + table.visible-xs { + display: table; + } + + /* line 11, ../sass/bootstrap/mixins/_responsive-visibility.scss */ + tr.visible-xs { + display: table-row !important; + } + + /* line 12, ../sass/bootstrap/mixins/_responsive-visibility.scss */ + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (max-width: 767px) { + /* line 49, ../sass/bootstrap/_responsive-utilities.scss */ + .visible-xs-block { + display: block !important; + } +} + +@media (max-width: 767px) { + /* line 54, ../sass/bootstrap/_responsive-utilities.scss */ + .visible-xs-inline { + display: inline !important; + } +} + +@media (max-width: 767px) { + /* line 59, ../sass/bootstrap/_responsive-utilities.scss */ + .visible-xs-inline-block { + display: inline-block !important; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + /* line 7, ../sass/bootstrap/mixins/_responsive-visibility.scss */ + .visible-sm { + display: block !important; + } + + /* line 10, ../sass/bootstrap/mixins/_responsive-visibility.scss */ + table.visible-sm { + display: table; + } + + /* line 11, ../sass/bootstrap/mixins/_responsive-visibility.scss */ + tr.visible-sm { + display: table-row !important; + } + + /* line 12, ../sass/bootstrap/mixins/_responsive-visibility.scss */ + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + /* line 68, ../sass/bootstrap/_responsive-utilities.scss */ + .visible-sm-block { + display: block !important; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + /* line 73, ../sass/bootstrap/_responsive-utilities.scss */ + .visible-sm-inline { + display: inline !important; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + /* line 78, ../sass/bootstrap/_responsive-utilities.scss */ + .visible-sm-inline-block { + display: inline-block !important; + } +} + +@media (min-width: 992px) and (max-width: 1199px) { + /* line 7, ../sass/bootstrap/mixins/_responsive-visibility.scss */ + .visible-md { + display: block !important; + } + + /* line 10, ../sass/bootstrap/mixins/_responsive-visibility.scss */ + table.visible-md { + display: table; + } + + /* line 11, ../sass/bootstrap/mixins/_responsive-visibility.scss */ + tr.visible-md { + display: table-row !important; + } + + /* line 12, ../sass/bootstrap/mixins/_responsive-visibility.scss */ + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + /* line 87, ../sass/bootstrap/_responsive-utilities.scss */ + .visible-md-block { + display: block !important; + } +} + +@media (min-width: 992px) and (max-width: 1199px) { + /* line 92, ../sass/bootstrap/_responsive-utilities.scss */ + .visible-md-inline { + display: inline !important; + } +} + +@media (min-width: 992px) and (max-width: 1199px) { + /* line 97, ../sass/bootstrap/_responsive-utilities.scss */ + .visible-md-inline-block { + display: inline-block !important; + } +} + +@media (min-width: 1200px) { + /* line 7, ../sass/bootstrap/mixins/_responsive-visibility.scss */ + .visible-lg { + display: block !important; + } + + /* line 10, ../sass/bootstrap/mixins/_responsive-visibility.scss */ + table.visible-lg { + display: table; + } + + /* line 11, ../sass/bootstrap/mixins/_responsive-visibility.scss */ + tr.visible-lg { + display: table-row !important; + } + + /* line 12, ../sass/bootstrap/mixins/_responsive-visibility.scss */ + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + /* line 106, ../sass/bootstrap/_responsive-utilities.scss */ + .visible-lg-block { + display: block !important; + } +} + +@media (min-width: 1200px) { + /* line 111, ../sass/bootstrap/_responsive-utilities.scss */ + .visible-lg-inline { + display: inline !important; + } +} + +@media (min-width: 1200px) { + /* line 116, ../sass/bootstrap/_responsive-utilities.scss */ + .visible-lg-inline-block { + display: inline-block !important; + } +} + +@media (max-width: 767px) { + /* line 18, ../sass/bootstrap/mixins/_responsive-visibility.scss */ + .hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + /* line 18, ../sass/bootstrap/mixins/_responsive-visibility.scss */ + .hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + /* line 18, ../sass/bootstrap/mixins/_responsive-visibility.scss */ + .hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + /* line 18, ../sass/bootstrap/mixins/_responsive-visibility.scss */ + .hidden-lg { + display: none !important; + } +} +/* line 18, ../sass/bootstrap/mixins/_responsive-visibility.scss */ +.visible-print { + display: none !important; +} + +@media print { + /* line 7, ../sass/bootstrap/mixins/_responsive-visibility.scss */ + .visible-print { + display: block !important; + } + + /* line 10, ../sass/bootstrap/mixins/_responsive-visibility.scss */ + table.visible-print { + display: table; + } + + /* line 11, ../sass/bootstrap/mixins/_responsive-visibility.scss */ + tr.visible-print { + display: table-row !important; + } + + /* line 12, ../sass/bootstrap/mixins/_responsive-visibility.scss */ + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +/* line 150, ../sass/bootstrap/_responsive-utilities.scss */ +.visible-print-block { + display: none !important; +} +@media print { + /* line 150, ../sass/bootstrap/_responsive-utilities.scss */ + .visible-print-block { + display: block !important; + } +} + +/* line 157, ../sass/bootstrap/_responsive-utilities.scss */ +.visible-print-inline { + display: none !important; +} +@media print { + /* line 157, ../sass/bootstrap/_responsive-utilities.scss */ + .visible-print-inline { + display: inline !important; + } +} + +/* line 164, ../sass/bootstrap/_responsive-utilities.scss */ +.visible-print-inline-block { + display: none !important; +} +@media print { + /* line 164, ../sass/bootstrap/_responsive-utilities.scss */ + .visible-print-inline-block { + display: inline-block !important; + } +} + +@media print { + /* line 18, ../sass/bootstrap/mixins/_responsive-visibility.scss */ + .hidden-print { + display: none !important; + } +} +/* line 2, ../sass/_pbs.overrides.scss */ +.help-block { + font-size: 12px !important; + font-style: italic; +} + +/* line 6, ../sass/_pbs.overrides.scss */ +.form-actions .btn-info { + min-width: 100px; + margin-left: 8px; +} + +/* line 10, ../sass/_pbs.overrides.scss */ +.form-horizontal { + width: 100%; +} + +/* line 13, ../sass/_pbs.overrides.scss */ +table td.control-label { + vertical-align: top; + text-transform: capitalize; +} + +/* line 17, ../sass/_pbs.overrides.scss */ +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"], +select { + color: #393939; +} + +/* line 35, ../sass/_pbs.overrides.scss */ +textarea { + min-height: 100px; + resize: vertical; +} diff --git a/filer/static/admin/libs/bootstrap/css/bootstrap/glyphicons-halflings-regular.eot b/filer/static/admin/libs/bootstrap/css/bootstrap/glyphicons-halflings-regular.eot new file mode 100644 index 000000000..4a4ca865d Binary files /dev/null and b/filer/static/admin/libs/bootstrap/css/bootstrap/glyphicons-halflings-regular.eot differ diff --git a/filer/static/admin/libs/bootstrap/css/bootstrap/glyphicons-halflings-regular.svg b/filer/static/admin/libs/bootstrap/css/bootstrap/glyphicons-halflings-regular.svg new file mode 100644 index 000000000..e3e2dc739 --- /dev/null +++ b/filer/static/admin/libs/bootstrap/css/bootstrap/glyphicons-halflings-regular.svg @@ -0,0 +1,229 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/filer/static/admin/libs/bootstrap/css/bootstrap/glyphicons-halflings-regular.ttf b/filer/static/admin/libs/bootstrap/css/bootstrap/glyphicons-halflings-regular.ttf new file mode 100644 index 000000000..67fa00bf8 Binary files /dev/null and b/filer/static/admin/libs/bootstrap/css/bootstrap/glyphicons-halflings-regular.ttf differ diff --git a/filer/static/admin/libs/bootstrap/css/bootstrap/glyphicons-halflings-regular.woff b/filer/static/admin/libs/bootstrap/css/bootstrap/glyphicons-halflings-regular.woff new file mode 100644 index 000000000..8c54182aa Binary files /dev/null and b/filer/static/admin/libs/bootstrap/css/bootstrap/glyphicons-halflings-regular.woff differ diff --git a/filer/static/admin/libs/bootstrap/js/bootstrap.min.js b/filer/static/admin/libs/bootstrap/js/bootstrap.min.js new file mode 100644 index 000000000..7c1561a8b --- /dev/null +++ b/filer/static/admin/libs/bootstrap/js/bootstrap.min.js @@ -0,0 +1,6 @@ +/*! + * Bootstrap v3.2.0 (http://getbootstrap.com) + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.2.0",d.prototype.close=function(b){function c(){f.detach().trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one("bsTransitionEnd",c).emulateTransitionEnd(150):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.2.0",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),d[e](null==f[b]?this.options[b]:f[b]),setTimeout(a.proxy(function(){"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}a&&this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b).on("keydown.bs.carousel",a.proxy(this.keydown,this)),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.2.0",c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},c.prototype.keydown=function(a){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.to=function(b){var c=this,d=this.getItemIndex(this.$active=this.$element.find(".item.active"));return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}if(e.hasClass("active"))return this.sliding=!1;var j=e[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:g});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,f&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(e)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:g});return a.support.transition&&this.$element.hasClass("slide")?(e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one("bsTransitionEnd",function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(1e3*d.css("transition-duration").slice(0,-1))):(d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger(m)),f&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b);!e&&f.toggle&&"show"==b&&(b=!b),e||d.data("bs.collapse",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};c.VERSION="3.2.0",c.DEFAULTS={toggle:!0},c.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},c.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var c=a.Event("show.bs.collapse");if(this.$element.trigger(c),!c.isDefaultPrevented()){var d=this.$parent&&this.$parent.find("> .panel > .in");if(d&&d.length){var e=d.data("bs.collapse");if(e&&e.transitioning)return;b.call(d,"hide"),e||d.data("bs.collapse",null)}var f=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[f](0),this.transitioning=1;var g=function(){this.$element.removeClass("collapsing").addClass("collapse in")[f](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return g.call(this);var h=a.camelCase(["scroll",f].join("-"));this.$element.one("bsTransitionEnd",a.proxy(g,this)).emulateTransitionEnd(350)[f](this.$element[0][h])}}},c.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(d,this)).emulateTransitionEnd(350):d.call(this)}}},c.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var d=a.fn.collapse;a.fn.collapse=b,a.fn.collapse.Constructor=c,a.fn.collapse.noConflict=function(){return a.fn.collapse=d,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(c){var d,e=a(this),f=e.attr("data-target")||c.preventDefault()||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""),g=a(f),h=g.data("bs.collapse"),i=h?"toggle":e.data(),j=e.attr("data-parent"),k=j&&a(j);h&&h.transitioning||(k&&k.find('[data-toggle="collapse"][data-parent="'+j+'"]').not(e).addClass("collapsed"),e[g.hasClass("in")?"addClass":"removeClass"]("collapsed")),b.call(g,i)})}(jQuery),+function(a){"use strict";function b(b){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=c(a(this)),e={relatedTarget:this};d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown",e)),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown",e))}))}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.2.0",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('');var j=f.parent();if(f.css("position")=="static"){j.css({position:"relative"});f.css({position:"relative"})}else{var i=f.css("top");if(isNaN(parseInt(i,10))){i="auto"}var h=f.css("left");if(isNaN(parseInt(h,10))){h="auto"}j.css({position:f.css("position"),top:i,left:h,zIndex:f.css("z-index")}).show();f.css({position:"relative",top:0,left:0})}j.css(g);return j},removeWrapper:function(f){if(f.parent().is(".ui-effects-wrapper")){return f.parent().replaceWith(f)}return f},setTransition:function(g,i,f,h){h=h||{};d.each(i,function(k,j){unit=g.cssUnit(j);if(unit[0]>0){h[j]=unit[0]*f+unit[1]}});return h},animateClass:function(h,i,k,j){var f=(typeof k=="function"?k:(j?j:null));var g=(typeof k=="string"?k:null);return this.each(function(){var q={};var o=d(this);var p=o.attr("style")||"";if(typeof p=="object"){p=p.cssText}if(h.toggle){o.hasClass(h.toggle)?h.remove=h.toggle:h.add=h.toggle}var l=d.extend({},(document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle));if(h.add){o.addClass(h.add)}if(h.remove){o.removeClass(h.remove)}var m=d.extend({},(document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle));if(h.add){o.removeClass(h.add)}if(h.remove){o.addClass(h.remove)}for(var r in m){if(typeof m[r]!="function"&&m[r]&&r.indexOf("Moz")==-1&&r.indexOf("length")==-1&&m[r]!=l[r]&&(r.match(/color/i)||(!r.match(/color/i)&&!isNaN(parseInt(m[r],10))))&&(l.position!="static"||(l.position=="static"&&!r.match(/left|top|bottom|right/)))){q[r]=m[r]}}o.animate(q,i,g,function(){if(typeof d(this).attr("style")=="object"){d(this).attr("style")["cssText"]="";d(this).attr("style")["cssText"]=p}else{d(this).attr("style",p)}if(h.add){d(this).addClass(h.add)}if(h.remove){d(this).removeClass(h.remove)}if(f){f.apply(this,arguments)}})})}};function c(g,f){var i=g[1]&&g[1].constructor==Object?g[1]:{};if(f){i.mode=f}var h=g[1]&&g[1].constructor!=Object?g[1]:(i.duration?i.duration:g[2]);h=d.fx.off?0:typeof h==="number"?h:d.fx.speeds[h]||d.fx.speeds._default;var j=i.callback||(d.isFunction(g[1])&&g[1])||(d.isFunction(g[2])&&g[2])||(d.isFunction(g[3])&&g[3]);return[g[0],i,h,j]}d.fn.extend({_show:d.fn.show,_hide:d.fn.hide,__toggle:d.fn.toggle,_addClass:d.fn.addClass,_removeClass:d.fn.removeClass,_toggleClass:d.fn.toggleClass,effect:function(g,f,h,i){return d.effects[g]?d.effects[g].call(this,{method:g,options:f||{},duration:h,callback:i}):null},show:function(){if(!arguments[0]||(arguments[0].constructor==Number||(/(slow|normal|fast)/).test(arguments[0]))){return this._show.apply(this,arguments)}else{return this.effect.apply(this,c(arguments,"show"))}},hide:function(){if(!arguments[0]||(arguments[0].constructor==Number||(/(slow|normal|fast)/).test(arguments[0]))){return this._hide.apply(this,arguments)}else{return this.effect.apply(this,c(arguments,"hide"))}},toggle:function(){if(!arguments[0]||(arguments[0].constructor==Number||(/(slow|normal|fast)/).test(arguments[0]))||(d.isFunction(arguments[0])||typeof arguments[0]=="boolean")){return this.__toggle.apply(this,arguments)}else{return this.effect.apply(this,c(arguments,"toggle"))}},addClass:function(g,f,i,h){return f?d.effects.animateClass.apply(this,[{add:g},f,i,h]):this._addClass(g)},removeClass:function(g,f,i,h){return f?d.effects.animateClass.apply(this,[{remove:g},f,i,h]):this._removeClass(g)},toggleClass:function(g,f,i,h){return((typeof f!=="boolean")&&f)?d.effects.animateClass.apply(this,[{toggle:g},f,i,h]):this._toggleClass(g,f)},morph:function(f,h,g,j,i){return d.effects.animateClass.apply(this,[{add:h,remove:f},g,j,i])},switchClass:function(){return this.morph.apply(this,arguments)},cssUnit:function(f){var g=this.css(f),h=[];d.each(["em","px","%","pt"],function(j,k){if(g.indexOf(k)>0){h=[parseFloat(g),k]}});return h}});d.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","color","outlineColor"],function(g,f){d.fx.step[f]=function(h){if(h.state==0){h.start=e(h.elem,f);h.end=b(h.end)}h.elem.style[f]="rgb("+[Math.max(Math.min(parseInt((h.pos*(h.end[0]-h.start[0]))+h.start[0],10),255),0),Math.max(Math.min(parseInt((h.pos*(h.end[1]-h.start[1]))+h.start[1],10),255),0),Math.max(Math.min(parseInt((h.pos*(h.end[2]-h.start[2]))+h.start[2],10),255),0)].join(",")+")"}});function b(g){var f;if(g&&g.constructor==Array&&g.length==3){return g}if(f=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(g)){return[parseInt(f[1],10),parseInt(f[2],10),parseInt(f[3],10)]}if(f=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(g)){return[parseFloat(f[1])*2.55,parseFloat(f[2])*2.55,parseFloat(f[3])*2.55]}if(f=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(g)){return[parseInt(f[1],16),parseInt(f[2],16),parseInt(f[3],16)]}if(f=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(g)){return[parseInt(f[1]+f[1],16),parseInt(f[2]+f[2],16),parseInt(f[3]+f[3],16)]}if(f=/rgba\(0, 0, 0, 0\)/.exec(g)){return a.transparent}return a[d.trim(g).toLowerCase()]}function e(h,f){var g;do{g=d.curCSS(h,f);if(g!=""&&g!="transparent"||d.nodeName(h,"body")){break}f="backgroundColor"}while(h=h.parentNode);return b(g)}var a={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]};d.easing.jswing=d.easing.swing;d.extend(d.easing,{def:"easeOutQuad",swing:function(g,h,f,j,i){return d.easing[d.easing.def](g,h,f,j,i)},easeInQuad:function(g,h,f,j,i){return j*(h/=i)*h+f},easeOutQuad:function(g,h,f,j,i){return -j*(h/=i)*(h-2)+f},easeInOutQuad:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h+f}return -j/2*((--h)*(h-2)-1)+f},easeInCubic:function(g,h,f,j,i){return j*(h/=i)*h*h+f},easeOutCubic:function(g,h,f,j,i){return j*((h=h/i-1)*h*h+1)+f},easeInOutCubic:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h*h+f}return j/2*((h-=2)*h*h+2)+f},easeInQuart:function(g,h,f,j,i){return j*(h/=i)*h*h*h+f},easeOutQuart:function(g,h,f,j,i){return -j*((h=h/i-1)*h*h*h-1)+f},easeInOutQuart:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h*h*h+f}return -j/2*((h-=2)*h*h*h-2)+f},easeInQuint:function(g,h,f,j,i){return j*(h/=i)*h*h*h*h+f},easeOutQuint:function(g,h,f,j,i){return j*((h=h/i-1)*h*h*h*h+1)+f},easeInOutQuint:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h*h*h*h+f}return j/2*((h-=2)*h*h*h*h+2)+f},easeInSine:function(g,h,f,j,i){return -j*Math.cos(h/i*(Math.PI/2))+j+f},easeOutSine:function(g,h,f,j,i){return j*Math.sin(h/i*(Math.PI/2))+f},easeInOutSine:function(g,h,f,j,i){return -j/2*(Math.cos(Math.PI*h/i)-1)+f},easeInExpo:function(g,h,f,j,i){return(h==0)?f:j*Math.pow(2,10*(h/i-1))+f},easeOutExpo:function(g,h,f,j,i){return(h==i)?f+j:j*(-Math.pow(2,-10*h/i)+1)+f},easeInOutExpo:function(g,h,f,j,i){if(h==0){return f}if(h==i){return f+j}if((h/=i/2)<1){return j/2*Math.pow(2,10*(h-1))+f}return j/2*(-Math.pow(2,-10*--h)+2)+f},easeInCirc:function(g,h,f,j,i){return -j*(Math.sqrt(1-(h/=i)*h)-1)+f},easeOutCirc:function(g,h,f,j,i){return j*Math.sqrt(1-(h=h/i-1)*h)+f},easeInOutCirc:function(g,h,f,j,i){if((h/=i/2)<1){return -j/2*(Math.sqrt(1-h*h)-1)+f}return j/2*(Math.sqrt(1-(h-=2)*h)+1)+f},easeInElastic:function(g,i,f,m,l){var j=1.70158;var k=0;var h=m;if(i==0){return f}if((i/=l)==1){return f+m}if(!k){k=l*0.3}if(h").css({position:"absolute",visibility:"visible",left:-d*(g/e),top:-f*(c/k)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:g/e,height:c/k,left:l.left+d*(g/e)+(b.options.mode=="show"?(d-Math.floor(e/2))*(g/e):0),top:l.top+f*(c/k)+(b.options.mode=="show"?(f-Math.floor(k/2))*(c/k):0),opacity:b.options.mode=="show"?0:1}).animate({left:l.left+d*(g/e)+(b.options.mode=="show"?0:(d-Math.floor(e/2))*(g/e)),top:l.top+f*(c/k)+(b.options.mode=="show"?0:(f-Math.floor(k/2))*(c/k)),opacity:b.options.mode=="show"?1:0},b.duration||500)}}setTimeout(function(){b.options.mode=="show"?h.css({visibility:"visible"}):h.css({visibility:"visible"}).hide();if(b.callback){b.callback.apply(h[0])}h.dequeue();a("div.ui-effects-explode").remove()},b.duration||500)})}})(jQuery);;/* - * jQuery UI Effects Fold 1.7.2 - * - * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. - * - * http://docs.jquery.com/UI/Effects/Fold - * - * Depends: - * effects.core.js - */ -(function(a){a.effects.fold=function(b){return this.queue(function(){var e=a(this),k=["position","top","left"];var h=a.effects.setMode(e,b.options.mode||"hide");var o=b.options.size||15;var n=!(!b.options.horizFirst);var g=b.duration?b.duration/2:a.fx.speeds._default/2;a.effects.save(e,k);e.show();var d=a.effects.createWrapper(e).css({overflow:"hidden"});var i=((h=="show")!=n);var f=i?["width","height"]:["height","width"];var c=i?[d.width(),d.height()]:[d.height(),d.width()];var j=/([0-9]+)%/.exec(o);if(j){o=parseInt(j[1],10)/100*c[h=="hide"?0:1]}if(h=="show"){d.css(n?{height:0,width:o}:{height:o,width:0})}var m={},l={};m[f[0]]=h=="show"?c[0]:o;l[f[1]]=h=="show"?c[1]:0;d.animate(m,g,b.options.easing).animate(l,g,b.options.easing,function(){if(h=="hide"){e.hide()}a.effects.restore(e,k);a.effects.removeWrapper(e);if(b.callback){b.callback.apply(e[0],arguments)}e.dequeue()})})}})(jQuery);;/* - * jQuery UI Effects Highlight 1.7.2 - * - * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. - * - * http://docs.jquery.com/UI/Effects/Highlight - * - * Depends: - * effects.core.js - */ -(function(a){a.effects.highlight=function(b){return this.queue(function(){var e=a(this),d=["backgroundImage","backgroundColor","opacity"];var h=a.effects.setMode(e,b.options.mode||"show");var c=b.options.color||"#ffff99";var g=e.css("backgroundColor");a.effects.save(e,d);e.show();e.css({backgroundImage:"none",backgroundColor:c});var f={backgroundColor:g};if(h=="hide"){f.opacity=0}e.animate(f,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){if(h=="hide"){e.hide()}a.effects.restore(e,d);if(h=="show"&&a.browser.msie){this.style.removeAttribute("filter")}if(b.callback){b.callback.apply(this,arguments)}e.dequeue()}})})}})(jQuery);;/* - * jQuery UI Effects Pulsate 1.7.2 - * - * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. - * - * http://docs.jquery.com/UI/Effects/Pulsate - * - * Depends: - * effects.core.js - */ -(function(a){a.effects.pulsate=function(b){return this.queue(function(){var d=a(this);var g=a.effects.setMode(d,b.options.mode||"show");var f=b.options.times||5;var e=b.duration?b.duration/2:a.fx.speeds._default/2;if(g=="hide"){f--}if(d.is(":hidden")){d.css("opacity",0);d.show();d.animate({opacity:1},e,b.options.easing);f=f-2}for(var c=0;c').appendTo(document.body).addClass(b.options.className).css({top:d.top,left:d.left,height:f.innerHeight(),width:f.innerWidth(),position:"absolute"}).animate(g,b.duration,b.options.easing,function(){c.remove();(b.callback&&b.callback.apply(f[0],arguments));f.dequeue()})})}})(jQuery);; \ No newline at end of file diff --git a/filer/static/filer/js/jquery.fancytree-all.min.js b/filer/static/filer/js/jquery.fancytree-all.min.js new file mode 100644 index 000000000..1f54dd539 --- /dev/null +++ b/filer/static/filer/js/jquery.fancytree-all.min.js @@ -0,0 +1,45 @@ +/*! jQuery Fancytree Plugin - 2.4.1 - 2014-09-23T19:33 + * https://github.com/mar10/fancytree + * Copyright (c) 2014 Martin Wendt; Licensed MIT */ +(function( factory ) { + if ( typeof define === "function" && define.amd ) { + define( [ "jquery", "jquery-ui" ], factory ); + } else { + factory( jQuery ); + } +}(function( $ ) { + + +!function(a,b,c,d){"use strict";function e(b){b=b||"",a.error("Not implemented: "+b)}function f(b,c){b||(c=c?": "+c:"",a.error("Fancytree assertion failed"+c))}function g(a,c){var d,e,f=b.console?b.console[a]:null;if(f)if(f.apply)f.apply(b.console,c);else{for(e="",d=0;de;return!0}function j(a,b,c,d,e){var f=function(){var c=b[a],f=d[a],g=b.ext[e],h=function(){return c.apply(b,arguments)};return function(){var a=b._local,c=b._super;try{return b._local=g,b._super=h,f.apply(b,arguments)}finally{b._local=a,b._super=c}}}();return f}function k(b,c,d,e){for(var f in d)"function"==typeof d[f]?"function"==typeof b[f]?b[f]=j(f,b,c,d,e):"_"===f.charAt(0)?b.ext[e][f]=j(f,b,c,d,e):a.error("Could not override tree."+f+". Use prefix '_' to create tree."+e+"._"+f):"options"!==f&&(b.ext[e][f]=d[f])}function l(b,c){return b===d?a.Deferred(function(){this.resolve()}).promise():a.Deferred(function(){this.resolveWith(b,c)}).promise()}function m(b,c){return b===d?a.Deferred(function(){this.reject()}).promise():a.Deferred(function(){this.rejectWith(b,c)}).promise()}function n(a,b){return function(){a.resolveWith(b)}}function o(b){var c=a.extend({},b.data()),d=c.json;return delete c.fancytree,d&&(delete c.json,c=a.extend(c,d)),c}function p(a){return a=a.toLowerCase(),function(b){return b.title.toLowerCase().indexOf(a)>=0}}function q(b,c){var d,e,g,h;for(this.parent=b,this.tree=b.tree,this.ul=null,this.li=null,this.statusNodeType=null,this._isLoading=!1,this._error=null,this.data={},d=0,e=x.length;e>d;d++)g=x[d],this[g]=c[g];c.data&&a.extend(this.data,c.data);for(g in c)y[g]||a.isFunction(c[g])||z[g]||(this.data[g]=c[g]);null==this.key?this.tree.options.defaultKey?(this.key=this.tree.options.defaultKey(this),f(this.key,"defaultKey() must return a unique key")):this.key="_"+t._nextNodeKey++:this.key=""+this.key,c.active&&(f(null===this.tree.activeNode,"only one active node allowed"),this.tree.activeNode=this),c.selected&&(this.tree.lastSelectedNode=this),this.children=null,h=c.children,h&&h.length&&this._setChildren(h),this.tree._callHook("treeRegisterNode",this.tree,!0,this)}function r(b){this.widget=b,this.$div=b.element,this.options=b.options,this.options&&a.isFunction(this.options.lazyload)&&(a.isFunction(this.options.lazyLoad)||(this.options.lazyLoad=function(){t.warn("The 'lazyload' event is deprecated since 2014-02-25. Use 'lazyLoad' (with uppercase L) instead."),b.options.lazyload.apply(this,arguments)})),this.options&&a.isFunction(this.options.loaderror)&&a.error("The 'loaderror' event was renamed since 2014-07-03. Use 'loadError' (with uppercase E) instead."),this.ext={},this.data=o(this.$div),this._id=null==this.options.id?a.ui.fancytree._nextId++:this.options.id,this._ns=".fancytree-"+this._id,this.activeNode=null,this.focusNode=null,this._hasFocus=null,this.lastSelectedNode=null,this.systemFocusElement=null,this.statusClassPropName="span",this.ariaPropName="li",this.nodeContainerAttrName="li",this.$div.find(">ul.fancytree-container").remove();var c,d={tree:this};this.rootNode=new q(d,{title:"root",key:"root_"+this._id,children:null,expanded:!0}),this.rootNode.parent=null,c=a("
    ",{"class":"ui-fancytree fancytree-container"}).appendTo(this.$div),this.$container=c,this.rootNode.ul=c[0],null==this.options.debugLevel&&(this.options.debugLevel=t.debugLevel),this.$container.attr("tabindex",this.options.tabbable?"0":"-1"),this.options.aria&&this.$container.attr("role","tree").attr("aria-multiselectable",!0)}if(a.ui.fancytree&&a.ui.fancytree.version)return void a.ui.fancytree.warn("Fancytree: ignored duplicate include");var s,t=null,u={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"},v="active expanded focus folder hideCheckbox lazy selected unselectable".split(" "),w={},x="expanded extraClasses folder hideCheckbox key lazy refKey selected title tooltip unselectable".split(" "),y={},z={active:!0,children:!0,data:!0,focus:!0};for(s=0;sb;b++)if(d[b].key===a)return d[b]}else{if("number"==typeof a)return this.children[a];if(a.parent===this)return a}return null},_setChildren:function(a){f(a&&(!this.children||0===this.children.length),"only init supported"),this.children=[];for(var b=0,c=a.length;c>b;b++)this.children.push(new q(this,a[b]))},addChildren:function(b,c){var d,e,g,h=null,i=[];for(a.isPlainObject(b)&&(b=[b]),this.children||(this.children=[]),d=0,e=b.length;e>d;d++)i.push(new q(this,b[d]));return h=i[0],null==c?this.children=this.children.concat(i):(c=this._findDirectChild(c),g=a.inArray(c,this.children),f(g>=0,"insertBefore must be an existing child"),this.children.splice.apply(this.children,[g,0].concat(i))),(!this.parent||this.parent.ul||this.tr)&&this.render(),3===this.tree.options.selectMode&&this.fixSelection3FromEndNodes(),h},addNode:function(a,b){switch((b===d||"over"===b)&&(b="child"),b){case"after":return this.getParent().addChildren(a,this.getNextSibling());case"before":return this.getParent().addChildren(a,this);case"child":case"over":return this.addChildren(a)}f(!1,"Invalid mode: "+b)},appendSibling:function(a){return this.addNode(a,"after")},applyPatch:function(b){if(null===b)return this.remove(),l(this);var c,d,e,f={children:!0,expanded:!0,parent:!0};for(c in b)e=b[c],f[c]||a.isFunction(e)||(y[c]?this[c]=e:this.data[c]=e);return b.hasOwnProperty("children")&&(this.removeChildren(),b.children&&this._setChildren(b.children)),this.isVisible()&&(this.renderTitle(),this.renderStatus()),d=b.hasOwnProperty("expanded")?this.setExpanded(b.expanded):l(this)},collapseSiblings:function(){return this.tree._callHook("nodeCollapseSiblings",this)},copyTo:function(a,b,c){return a.addNode(this.toDict(!0,c),b)},countChildren:function(a){var b,c,d,e=this.children;if(!e)return 0;if(d=e.length,a!==!1)for(b=0,c=d;c>b;b++)d+=e[b].countChildren();return d},debug:function(){this.tree.options.debugLevel>=2&&(Array.prototype.unshift.call(arguments,this.toString()),g("debug",arguments))},discard:function(){return this.warn("FancytreeNode.discard() is deprecated since 2014-02-16. Use .resetLazy() instead."),this.resetLazy()},findAll:function(b){b=a.isFunction(b)?b:p(b);var c=[];return this.visit(function(a){b(a)&&c.push(a)}),c},findFirst:function(b){b=a.isFunction(b)?b:p(b);var c=null;return this.visit(function(a){return b(a)?(c=a,!1):void 0}),c},_changeSelectStatusAttrs:function(a){var b=!1;switch(a){case!1:b=this.selected||this.partsel,this.selected=!1,this.partsel=!1;break;case!0:b=!this.selected||!this.partsel,this.selected=!0,this.partsel=!0;break;case d:b=this.selected||!this.partsel,this.selected=!1,this.partsel=!0;break;default:f(!1,"invalid state: "+a)}return b&&this.renderStatus(),b},fixSelection3AfterClick:function(){var a=this.isSelected();this.visit(function(b){b._changeSelectStatusAttrs(a)}),this.fixSelection3FromEndNodes()},fixSelection3FromEndNodes:function(){function a(b){var c,e,f,g,h,i,j,k=b.children;if(k&&k.length){for(i=!0,j=!1,c=0,e=k.length;e>c;c++)f=k[c],g=a(f),g!==!1&&(j=!0),g!==!0&&(i=!1);h=i?!0:j?d:!1}else h=!!b.selected;return b._changeSelectStatusAttrs(h),h}f(3===this.tree.options.selectMode,"expected selectMode 3"),a(this),this.visitParents(function(a){var b,c,e,f,g=a.children,h=!0,i=!1;for(b=0,c=g.length;c>b;b++)e=g[b],(e.selected||e.partsel)&&(i=!0),e.unselectable||e.selected||(h=!1);f=h?!0:i?d:!1,a._changeSelectStatusAttrs(f)})},fromDict:function(b){for(var c in b)y[c]?this[c]=b[c]:"data"===c?a.extend(this.data,b.data):a.isFunction(b[c])||z[c]||(this.data[c]=b[c]);b.children&&(this.removeChildren(),this.addChildren(b.children)),this.renderTitle()},getChildren:function(){return this.hasChildren()===d?d:this.children},getFirstChild:function(){return this.children?this.children[0]:null},getIndex:function(){return a.inArray(this,this.parent.children)},getIndexHier:function(b){b=b||".";var c=[];return a.each(this.getParentList(!1,!0),function(a,b){c.push(b.getIndex()+1)}),c.join(b)},getKeyPath:function(a){var b=[],c=this.tree.options.keyPathSeparator;return this.visitParents(function(a){a.parent&&b.unshift(a.key)},!a),c+b.join(c)},getLastChild:function(){return this.children?this.children[this.children.length-1]:null},getLevel:function(){for(var a=0,b=this.parent;b;)a++,b=b.parent;return a},getNextSibling:function(){if(this.parent){var a,b,c=this.parent.children;for(a=0,b=c.length-1;b>a;a++)if(c[a]===this)return c[a+1]}return null},getParent:function(){return this.parent},getParentList:function(a,b){for(var c=[],d=b?this:this.parent;d;)(a||d.parent)&&c.unshift(d),d=d.parent;return c},getPrevSibling:function(){if(this.parent){var a,b,c=this.parent.children;for(a=1,b=c.length;b>a;a++)if(c[a]===this)return c[a-1]}return null},hasChildren:function(){return this.lazy?null==this.children?d:0===this.children.length?!1:1===this.children.length&&this.children[0].isStatusNode()?d:!0:!(!this.children||!this.children.length)},hasFocus:function(){return this.tree.hasFocus()&&this.tree.focusNode===this},info:function(){this.tree.options.debugLevel>=1&&(Array.prototype.unshift.call(arguments,this.toString()),g("info",arguments))},isActive:function(){return this.tree.activeNode===this},isChildOf:function(a){return this.parent&&this.parent===a},isDescendantOf:function(a){if(!a||a.tree!==this.tree)return!1;for(var b=this.parent;b;){if(b===a)return!0;b=b.parent}return!1},isExpanded:function(){return!!this.expanded},isFirstSibling:function(){var a=this.parent;return!a||a.children[0]===this},isFolder:function(){return!!this.folder},isLastSibling:function(){var a=this.parent;return!a||a.children[a.children.length-1]===this},isLazy:function(){return!!this.lazy},isLoaded:function(){return!this.lazy||this.hasChildren()!==d},isLoading:function(){return!!this._isLoading},isRoot:function(){return this.isRootNode()},isRootNode:function(){return this.tree.rootNode===this},isSelected:function(){return!!this.selected},isStatusNode:function(){return!!this.statusNodeType},isTopLevel:function(){return this.tree.rootNode===this.parent},isUndefined:function(){return this.hasChildren()===d},isVisible:function(){var a,b,c=this.getParentList(!1,!1);for(a=0,b=c.length;b>a;a++)if(!c[a].expanded)return!1;return!0},lazyLoad:function(a){return this.warn("FancytreeNode.lazyLoad() is deprecated since 2014-02-16. Use .load() instead."),this.load(a)},load:function(a){var b,c,d=this;return a||this.isUndefined()?(this.isLoaded()&&this.resetLazy(),c=this.tree._triggerNodeEvent("lazyLoad",this),c===!1?l(this):(f("boolean"!=typeof c,"lazyLoad event must return source in data.result"),b=this.tree._callHook("nodeLoadChildren",this,c),this.expanded&&b.always(function(){d.render()}),b)):l(this)},makeVisible:function(b){var c,d=this,e=[],f=new a.Deferred,g=this.getParentList(!1,!1),h=g.length,i=!(b&&b.noAnimation===!0),j=!(b&&b.scrollIntoView===!1);for(c=h-1;c>=0;c--)e.push(g[c].setExpanded(!0,b));return a.when.apply(a,e).done(function(){j?d.scrollIntoView(i).done(function(){f.resolve()}):f.resolve()}),f.promise()},moveTo:function(b,c,e){(c===d||"over"===c)&&(c="child");var g,h=this.parent,i="child"===c?b:b.parent;if(this!==b){if(!this.parent)throw"Cannot move system root";if(i.isDescendantOf(this))throw"Cannot move a node to its own descendant";if(1===this.parent.children.length){if(this.parent===i)return;this.parent.children=this.parent.lazy?[]:null,this.parent.expanded=!1}else g=a.inArray(this,this.parent.children),f(g>=0),this.parent.children.splice(g,1);if(this.parent=i,i.hasChildren())switch(c){case"child":i.children.push(this);break;case"before":g=a.inArray(b,i.children),f(g>=0),i.children.splice(g,0,this);break;case"after":g=a.inArray(b,i.children),f(g>=0),i.children.splice(g+1,0,this);break;default:throw"Invalid mode "+c}else i.children=[this];e&&b.visit(e,!0),this.tree!==b.tree&&(this.warn("Cross-tree moveTo is experimantal!"),this.visit(function(a){a.tree=b.tree},!0)),h.isDescendantOf(i)||h.render(),i.isDescendantOf(h)||i===h||i.render()}},navigate:function(b,c){function d(d){if(d){try{d.makeVisible()}catch(e){}return a(d.span).is(":visible")?c===!1?d.setFocus():d.setActive():(d.debug("Navigate: skipping hidden node"),void d.navigate(b,c))}}var e,f,g=!0,h=a.ui.keyCode,i=null;switch(b){case h.BACKSPACE:this.parent&&this.parent.parent&&d(this.parent);break;case h.LEFT:this.expanded?(this.setExpanded(!1),d(this)):this.parent&&this.parent.parent&&d(this.parent);break;case h.RIGHT:this.expanded||!this.children&&!this.lazy?this.children&&this.children.length&&d(this.children[0]):(this.setExpanded(),d(this));break;case h.UP:for(i=this.getPrevSibling();i&&i.expanded&&i.children&&i.children.length;)i=i.children[i.children.length-1];!i&&this.parent&&this.parent.parent&&(i=this.parent),d(i);break;case h.DOWN:if(this.expanded&&this.children&&this.children.length)i=this.children[0];else for(f=this.getParentList(!1,!0),e=f.length-1;e>=0&&!(i=f[e].getNextSibling());e--);d(i);break;default:g=!1}},remove:function(){return this.parent.removeChild(this)},removeChild:function(a){return this.tree._callHook("nodeRemoveChild",this,a)},removeChildren:function(){return this.tree._callHook("nodeRemoveChildren",this)},render:function(a,b){return this.tree._callHook("nodeRender",this,a,b)},renderTitle:function(){return this.tree._callHook("nodeRenderTitle",this)},renderStatus:function(){return this.tree._callHook("nodeRenderStatus",this)},resetLazy:function(){this.removeChildren(),this.expanded=!1,this.lazy=!0,this.children=d,this.renderStatus()},scheduleAction:function(a,b){this.tree.timer&&clearTimeout(this.tree.timer),this.tree.timer=null;var c=this;switch(a){case"cancel":break;case"expand":this.tree.timer=setTimeout(function(){c.tree.debug("setTimeout: trigger expand"),c.setExpanded(!0)},b);break;case"activate":this.tree.timer=setTimeout(function(){c.tree.debug("setTimeout: trigger activate"),c.setActive(!0)},b);break;default:throw"Invalid mode "+a}},scrollIntoView:function(e,g){g!==d&&h(g)&&(this.warn("scrollIntoView() with 'topNode' option is deprecated since 2014-05-08. Use 'options.topNode' instead."),g={topNode:g});var i,j,k,l,m=a.extend({effects:e===!0?{duration:200,queue:!1}:e,scrollOfs:this.tree.options.scrollOfs,scrollParent:this.tree.options.scrollParent||this.tree.$container,topNode:null},g),n=new a.Deferred,o=this,p=a(this.span).height(),q=a(m.scrollParent),r=m.scrollOfs.top||0,s=m.scrollOfs.bottom||0,t=q.height(),u=q.scrollTop(),v=q,w=q[0]===b,x=m.topNode||null,y=null;return f(a(this.span).is(":visible"),"scrollIntoView node is invisible"),w?(j=a(this.span).offset().top,i=x&&x.span?a(x.span).offset().top:0,v=a("html,body")):(f(q[0]!==c&&q[0]!==c.body,"scrollParent should be an simple element or `window`, not document or body."),l=q.offset().top,j=a(this.span).offset().top-l+u,i=x?a(x.span).offset().top-l+u:0,k=Math.max(0,q.innerHeight()-q[0].clientHeight),t-=k),u+r>j?y=j-r:j+p>u+t-s&&(y=j+p-t+s,x&&(f(x.isRoot()||a(x.span).is(":visible"),"topNode must be visible"),y>i&&(y=i-r))),null!==y?m.effects?(m.effects.complete=function(){n.resolveWith(o)},v.stop(!0).animate({scrollTop:y},m.effects)):(v[0].scrollTop=y,n.resolveWith(this)):n.resolveWith(this),n.promise()},setActive:function(a,b){return this.tree._callHook("nodeSetActive",this,a,b)},setExpanded:function(a,b){return this.tree._callHook("nodeSetExpanded",this,a,b)},setFocus:function(a){return this.tree._callHook("nodeSetFocus",this,a)},setSelected:function(a){return this.tree._callHook("nodeSetSelected",this,a)},setStatus:function(a,b,c){return this.tree._callHook("nodeSetStatus",this,a,b,c)},setTitle:function(a){this.title=a,this.renderTitle()},sortChildren:function(a,b){var c,d,e=this.children;if(e){if(a=a||function(a,b){var c=a.title.toLowerCase(),d=b.title.toLowerCase();return c===d?0:c>d?1:-1},e.sort(a),b)for(c=0,d=e.length;d>c;c++)e[c].children&&e[c].sortChildren(a,"$norender$");"$norender$"!==b&&this.render()}},toDict:function(b,c){var d,e,f,g={},h=this;if(a.each(x,function(a,b){(h[b]||h[b]===!1)&&(g[b]=h[b])}),a.isEmptyObject(this.data)||(g.data=a.extend({},this.data),a.isEmptyObject(g.data)&&delete g.data),c&&c(g),b&&this.hasChildren())for(g.children=[],d=0,e=this.children.length;e>d;d++)f=this.children[d],f.isStatusNode()||g.children.push(f.toDict(!0,c));return g},toggleExpanded:function(){return this.tree._callHook("nodeToggleExpanded",this)},toggleSelected:function(){return this.tree._callHook("nodeToggleSelected",this)},toString:function(){return""},visit:function(a,b){var c,d,e=!0,f=this.children;if(b===!0&&(e=a(this),e===!1||"skip"===e))return e;if(f)for(c=0,d=f.length;d>c&&(e=f[c].visit(a,!0),e!==!1);c++);return e},visitAndLoad:function(b,c,d){var e,f,g,h=this;return b&&c===!0&&(f=b(h),f===!1||"skip"===f)?d?f:l():h.children||h.lazy?(e=new a.Deferred,g=[],h.load().done(function(){for(var c=0,d=h.children.length;d>c;c++){if(f=h.children[c].visitAndLoad(b,!0,!0),f===!1){e.reject();break}"skip"!==f&&g.push(f)}a.when.apply(this,g).then(function(){e.resolve()})}),e.promise()):l()},visitParents:function(a,b){if(b&&a(this)===!1)return!1;for(var c=this.parent;c;){if(a(c)===!1)return!1;c=c.parent}return!0},warn:function(){Array.prototype.unshift.call(arguments,this.toString()),g("warn",arguments)}},r.prototype={_makeHookContext:function(b,c,e){var f,g;return b.node!==d?(c&&b.originalEvent!==c&&a.error("invalid args"),f=b):b.tree?(g=b.tree,f={node:b,tree:g,widget:g.widget,options:g.widget.options,originalEvent:c}):b.widget?f={node:null,tree:b,widget:b.widget,options:b.widget.options,originalEvent:c}:a.error("invalid args"),e&&a.extend(f,e),f},_callHook:function(b,c){var d=this._makeHookContext(c),e=this[b],f=Array.prototype.slice.call(arguments,2);return a.isFunction(e)||a.error("_callHook('"+b+"') is not a function"),f.unshift(d),e.apply(this,f)},_requireExtension:function(b,c,d,e){d=!!d;var g=this._local.name,h=this.options.extensions,i=a.inArray(b,h)d;d++)e=b[d],f(2===e.length,"patchList must be an array of length-2-arrays"),g=e[0],h=e[1],i=null===g?this.rootNode:this.getNodeByKey(g),i?(c=new a.Deferred,k.push(c),i.applyPatch(h).always(n(c,i))):this.warn("could not find node with key '"+g+"'");return a.when.apply(a,k).promise()},count:function(){return this.rootNode.countChildren()},debug:function(){this.options.debugLevel>=2&&(Array.prototype.unshift.call(arguments,this.toString()),g("debug",arguments))},generateFormElements:function(b,c,d){var e,f=b!==!1?"ft_"+this._id+"[]":b,g=c!==!1?"ft_"+this._id+"_active":c,h="fancytree_result_"+this._id,i=a("#"+h);d="boolean"==typeof d?d:3===this.options.selectMode,i.length?i.empty():i=a("
    ",{id:h}).hide().insertAfter(this.$container),f&&(e=this.getSelectedNodes(d),a.each(e,function(b,c){i.append(a("",{type:"checkbox",name:f,value:c.key,checked:!0}))})),g&&this.activeNode&&i.append(a("",{type:"radio",name:g,value:this.activeNode.key,checked:!0}))},getActiveNode:function(){return this.activeNode},getFirstChild:function(){return this.rootNode.getFirstChild()},getFocusNode:function(){return this.focusNode},getNodeByKey:function(a,b){var d,e;return!b&&(d=c.getElementById(this.options.idPrefix+a))?d.ftnode?d.ftnode:null:(b=b||this.rootNode,e=null,b.visit(function(b){return b.key===a?(e=b,!1):void 0},!0),e)},getRootNode:function(){return this.rootNode},getSelectedNodes:function(a){var b=[];return this.rootNode.visit(function(c){return c.selected&&(b.push(c),a===!0)?"skip":void 0}),b},hasFocus:function(){return!!this._hasFocus},info:function(){this.options.debugLevel>=1&&(Array.prototype.unshift.call(arguments,this.toString()),g("info",arguments))},loadKeyPath:function(b,c,e){function f(a,b,d){c.call(r,b,"loading"),b.load().done(function(){r.loadKeyPath.call(r,l[a],c,b).always(n(d,r))}).fail(function(){r.warn("loadKeyPath: error loading: "+a+" (parent: "+o+")"),c.call(r,b,"error"),d.reject()})}var g,h,i,j,k,l,m,o,p,q=this.options.keyPathSeparator,r=this;for(a.isArray(b)||(b=[b]),l={},i=0;i"},_triggerNodeEvent:function(a,b,c,e){var f=this._makeHookContext(b,c,e),g=this.widget._trigger(a,c,f);return g!==!1&&f.result!==d?f.result:g},_triggerTreeEvent:function(a,b){var c=this._makeHookContext(this,b),e=this.widget._trigger(a,b,c);return e!==!1&&c.result!==d?c.result:e},visit:function(a){return this.rootNode.visit(a,!1)},warn:function(){Array.prototype.unshift.call(arguments,this.toString()),g("warn",arguments)}},a.extend(r.prototype,{nodeClick:function(a){var b,c,d=a.originalEvent,e=a.targetType,f=a.node;if("expander"===e)this._callHook("nodeToggleExpanded",a);else if("checkbox"===e)this._callHook("nodeToggleSelected",a),this._callHook("nodeSetFocus",a,!0);else{if(c=!1,b=!0,f.folder)switch(a.options.clickFolderMode){case 2:c=!0,b=!1;break;case 3:b=!0,c=!0}b&&(this.nodeSetFocus(a),this._callHook("nodeSetActive",a,!0)),c&&this._callHook("nodeToggleExpanded",a)}"a"===d.target.localName&&"fancytree-title"===d.target.className&&d.preventDefault()},nodeCollapseSiblings:function(a,b){var c,d,e,f=a.node;if(f.parent)for(c=f.parent.children,d=0,e=c.length;e>d;d++)c[d]!==f&&c[d].expanded&&this._callHook("nodeSetExpanded",c[d],!1,b)},nodeDblclick:function(a){"title"===a.targetType&&4===a.options.clickFolderMode&&this._callHook("nodeToggleExpanded",a),"title"===a.targetType&&a.originalEvent.preventDefault()},nodeKeydown:function(b){var c,d=b.originalEvent,e=b.node,f=b.tree,g=b.options,h=!0,i=!(d.ctrlKey||!g.autoActivate),j=a.ui.keyCode;switch(e||(this.rootNode.getFirstChild().setFocus(),e=b.node=this.focusNode,e.debug("Keydown force focus on first node")),d.which){case j.NUMPAD_ADD:case 187:f.nodeSetExpanded(b,!0);break;case j.NUMPAD_SUBTRACT:case 189:f.nodeSetExpanded(b,!1);break;case j.SPACE:g.checkbox?f.nodeToggleSelected(b):f.nodeSetActive(b,!0);break;case j.ENTER:f.nodeSetActive(b,!0);break;case j.BACKSPACE:case j.LEFT:case j.RIGHT:case j.UP:case j.DOWN:c=e.navigate(d.which,i);break;default:h=!1}h&&d.preventDefault()},nodeLoadChildren:function(b,c){var d,e,g,h=b.tree,i=b.node;return a.isFunction(c)&&(c=c()),c.url&&(d=a.extend({},b.options.ajax,c),d.debugDelay?(e=d.debugDelay,a.isArray(e)&&(e=e[0]+Math.random()*(e[1]-e[0])),i.debug("nodeLoadChildren waiting debug delay "+Math.round(e)+"ms"),d.debugDelay=!1,g=a.Deferred(function(b){setTimeout(function(){a.ajax(d).done(function(){b.resolveWith(this,arguments)}).fail(function(){b.rejectWith(this,arguments)})},e)})):g=a.ajax(d),c=new a.Deferred,g.done(function(d){var e,f;if("string"==typeof d&&a.error("Ajax request returned a string (did you get the JSON dataType wrong?)."),b.options.postProcess){if(f=h._triggerNodeEvent("postProcess",b,b.originalEvent,{response:d,error:null,dataType:this.dataType}),f.error)return e=a.isPlainObject(f.error)?f.error:{message:f.error},e=h._makeHookContext(i,null,e),void c.rejectWith(this,[e]);d=a.isArray(f)?f:d}else d&&d.hasOwnProperty("d")&&b.options.enableAspx&&(d="string"==typeof d.d?a.parseJSON(d.d):d.d);c.resolveWith(this,[d])}).fail(function(a,b,d){var e=h._makeHookContext(i,null,{error:a,args:Array.prototype.slice.call(arguments),message:d,details:a.status+": "+d});c.rejectWith(this,[e])})),a.isFunction(c.promise)&&(f(!i.isLoading()),h.nodeSetStatus(b,"loading"),c.done(function(){h.nodeSetStatus(b,"ok")}).fail(function(a){var c;c=a.node&&a.error&&a.message?a:h._makeHookContext(i,null,{error:a,args:Array.prototype.slice.call(arguments),message:a?a.message||a.toString():""}),h._triggerNodeEvent("loadError",c,null)!==!1&&h.nodeSetStatus(b,"error",c.message,c.details)})),a.when(c).done(function(b){var c;a.isPlainObject(b)&&(f(a.isArray(b.children),"source must contain (or be) an array of children"),f(i.isRoot(),"source may only be an object for root nodes"),c=b,b=b.children,delete c.children,a.extend(h.data,c)),f(a.isArray(b),"expected array of children"),i._setChildren(b),h._triggerNodeEvent("loadChildren",i)})},nodeLoadKeyPath:function(){},nodeRemoveChild:function(b,c){var d,e=b.node,g=b.options,h=a.extend({},b,{node:c}),i=e.children;return 1===i.length?(f(c===i[0]),this.nodeRemoveChildren(b)):(this.activeNode&&(c===this.activeNode||this.activeNode.isDescendantOf(c))&&this.activeNode.setActive(!1),this.focusNode&&(c===this.focusNode||this.focusNode.isDescendantOf(c))&&(this.focusNode=null),this.nodeRemoveMarkup(h),this.nodeRemoveChildren(h),d=a.inArray(c,i),f(d>=0),c.visit(function(a){a.parent=null},!0),this._callHook("treeRegisterNode",this,!1,c),g.removeNode&&g.removeNode.call(b.tree,{type:"removeNode"},h),void i.splice(d,1))},nodeRemoveChildMarkup:function(b){var c=b.node;c.ul&&(c.isRoot()?a(c.ul).empty():(a(c.ul).remove(),c.ul=null),c.visit(function(a){a.li=a.ul=null}))},nodeRemoveChildren:function(b){var c,d=b.tree,e=b.node,f=e.children,g=b.options;f&&(this.activeNode&&this.activeNode.isDescendantOf(e)&&this.activeNode.setActive(!1),this.focusNode&&this.focusNode.isDescendantOf(e)&&(this.focusNode=null),this.nodeRemoveChildMarkup(b),c=a.extend({},b),e.visit(function(a){a.parent=null,d._callHook("treeRegisterNode",d,!1,a),g.removeNode&&(c.node=a,g.removeNode.call(b.tree,{type:"removeNode"},c))}),e.children=e.lazy?[]:null,this.nodeRenderStatus(b))},nodeRemoveMarkup:function(b){var c=b.node;c.li&&(a(c.li).remove(),c.li=null),this.nodeRemoveChildMarkup(b)},nodeRender:function(b,d,e,g,h){var i,j,k,l,m,n,o,p=b.node,q=b.tree,r=b.options,s=r.aria,t=!1,u=p.parent,v=!u,w=p.children;if(v||u.ul){if(f(v||u.ul,"parent UL must exist"),v||(p.li&&(d||p.li.parentNode!==p.parent.ul)&&(p.li.parentNode!==p.parent.ul&&this.warn("unlink "+p+" (must be child of "+p.parent+")"),this.nodeRemoveMarkup(b)),p.li?this.nodeRenderStatus(b):(t=!0,p.li=c.createElement("li"),p.li.ftnode=p,p.key&&r.generateIds&&(p.li.id=r.idPrefix+p.key),p.span=c.createElement("span"),p.span.className="fancytree-node",s&&a(p.span).attr("aria-labelledby","ftal_"+p.key),p.li.appendChild(p.span),this.nodeRenderTitle(b),r.createNode&&r.createNode.call(q,{type:"createNode"},b)),r.renderNode&&r.renderNode.call(q,{type:"renderNode"},b)),w){if(v||p.expanded||e===!0){for(p.ul||(p.ul=c.createElement("ul"),(g===!0&&!h||!p.expanded)&&(p.ul.style.display="none"),s&&a(p.ul).attr("role","group"),p.li?p.li.appendChild(p.ul):p.tree.$div.append(p.ul)),l=0,m=w.length;m>l;l++)o=a.extend({},b,{node:w[l]}),this.nodeRender(o,d,e,!1,!0);for(i=p.ul.firstChild;i;)k=i.ftnode,k&&k.parent!==p?(p.debug("_fixParent: remove missing "+k,i),n=i.nextSibling,i.parentNode.removeChild(i),i=n):i=i.nextSibling;for(i=p.ul.firstChild,l=0,m=w.length-1;m>l;l++)j=w[l],k=i.ftnode,j!==k?p.ul.insertBefore(j.li,k.li):i=i.nextSibling}}else p.ul&&(this.warn("remove child markup for "+p),this.nodeRemoveChildMarkup(b));v||t&&u.ul.appendChild(p.li)}},nodeRenderTitle:function(a,b){var c,e,f,g,h,i,j=a.node,k=a.tree,l=a.options,m=l.aria,n=j.getLevel(),o=[],p=j.data.icon;b!==d&&(j.title=b),j.span&&(n1&&(j.lazy||(j.expanded=!0),o.push(m?"":"")):o.push(m?"":""),l.checkbox&&j.hideCheckbox!==!0&&!j.isStatusNode()&&o.push(m?"":""),g=m?" role='img'":"",(p===!0||p!==!1&&l.icons!==!1)&&(p&&"string"==typeof p?(p="/"===p.charAt(0)?p:(l.imagePath||"")+p,o.push("")):(e=l.iconClass&&l.iconClass.call(k,j,a)||j.data.iconclass||null,o.push(e?"":""))),f="",l.renderTitle&&(f=l.renderTitle.call(k,{type:"renderTitle"},a)||""),f||(i=j.tooltip?" title='"+j.tooltip.replace("'","'")+"'":"",c=m?" id='ftal_"+j.key+"'":"",g=m?" role='treeitem'":"",h=l.titlesTabbable?" tabindex='0'":"",f=""+j.title+""),o.push(f),j.span.innerHTML=o.join(""),this.nodeRenderStatus(a))},nodeRenderStatus:function(b){var c=b.node,d=b.tree,e=b.options,f=c.hasChildren(),g=c.isLastSibling(),h=e.aria,i=a(c.span).find(".fancytree-title"),j=e._classNames,k=[],l=c[d.statusClassPropName];l&&(k.push(j.node),d.activeNode===c&&k.push(j.active),d.focusNode===c?(k.push(j.focused),h&&i.attr("aria-activedescendant",!0)):h&&i.removeAttr("aria-activedescendant"),c.expanded?(k.push(j.expanded),h&&i.attr("aria-expanded",!0)):h&&i.removeAttr("aria-expanded"),c.folder&&k.push(j.folder),f!==!1&&k.push(j.hasChildren),g&&k.push(j.lastsib),c.lazy&&null==c.children&&k.push(j.lazy),c.partsel&&k.push(j.partsel),c._isLoading&&k.push(j.loading),c._error&&k.push(j.error),c.selected?(k.push(j.selected),h&&i.attr("aria-selected",!0)):h&&i.attr("aria-selected",!1),c.extraClasses&&k.push(c.extraClasses),k.push(f===!1?j.combinedExpanderPrefix+"n"+(g?"l":""):j.combinedExpanderPrefix+(c.expanded?"e":"c")+(c.lazy&&null==c.children?"d":"")+(g?"l":"")),k.push(j.combinedIconPrefix+(c.expanded?"e":"c")+(c.folder?"f":"")),l.className=k.join(" "),c.li&&(c.li.className=g?j.lastsib:""))},nodeSetActive:function(b,c,d){d=d||{};var e,g=b.node,h=b.tree,i=b.options,j=d.noEvents===!0,k=g===h.activeNode;return c=c!==!1,k===c?l(g):c&&!j&&this._triggerNodeEvent("beforeActivate",g,b.originalEvent)===!1?m(g,["rejected"]):void(c?(h.activeNode&&(f(h.activeNode!==g,"node was active (inconsistency)"),e=a.extend({},b,{node:h.activeNode}),h.nodeSetActive(e,!1),f(null===h.activeNode,"deactivate was out of sync?")),i.activeVisible&&g.makeVisible({scrollIntoView:!1}),h.activeNode=g,h.nodeRenderStatus(b),h.nodeSetFocus(b),j||h._triggerNodeEvent("activate",g,b.originalEvent)):(f(h.activeNode===g,"node was not active (inconsistency)"),h.activeNode=null,this.nodeRenderStatus(b),j||b.tree._triggerNodeEvent("deactivate",g,b.originalEvent)))},nodeSetExpanded:function(b,c,e){e=e||{};var f,g,h,i,j,k,n=b.node,o=b.tree,p=b.options,q=e.noAnimation===!0,r=e.noEvents===!0;if(c=c!==!1,n.expanded&&c||!n.expanded&&!c)return l(n);if(c&&!n.lazy&&!n.hasChildren())return l(n);if(!c&&n.getLevel()h;h++)this._callHook("nodeCollapseSiblings",j[h],e)}finally{p.autoCollapse=k}}return g.done(function(){c&&p.autoScroll&&!q?n.getLastChild().scrollIntoView(!0,{topNode:n}).always(function(){r||b.tree._triggerNodeEvent(c?"expand":"collapse",b)}):r||b.tree._triggerNodeEvent(c?"expand":"collapse",b)}),f=function(d){var e,f,g,h;if(n.expanded=c,o._callHook("nodeRender",b,!1,!1,!0),n.ul)if(g="none"!==n.ul.style.display,h=!!n.expanded,g===h)n.warn("nodeSetExpanded: UL.style.display already set");else{if(p.fx&&!q)return e=p.fx.duration||200,f=p.fx.easing,void a(n.ul).animate(p.fx,e,f,function(){d()});n.ul.style.display=n.expanded||!parent?"":"none"}d()},c&&n.lazy&&n.hasChildren()===d?n.load().done(function(){g.notifyWith&&g.notifyWith(n,["loaded"]),f(function(){g.resolveWith(n)})}).fail(function(a){f(function(){g.rejectWith(n,["load failed ("+a+")"])})}):f(function(){g.resolveWith(n)}),g.promise()},nodeSetFocus:function(b,c){var d,e=b.tree,f=b.node;if(c=c!==!1,e.focusNode){if(e.focusNode===f&&c)return;d=a.extend({},b,{node:e.focusNode}),e.focusNode=null,this._triggerNodeEvent("blur",d),this._callHook("nodeRenderStatus",d)}c&&(this.hasFocus()||(f.debug("nodeSetFocus: forcing container focus"),this._callHook("treeSetFocus",b,!0,!0)),f.makeVisible({scrollIntoView:!1}),e.focusNode=f,this._triggerNodeEvent("focus",b),b.options.autoScroll&&f.scrollIntoView(),this._callHook("nodeRenderStatus",b))},nodeSetSelected:function(a,b){var c=a.node,d=a.tree,e=a.options;if(b=b!==!1,c.debug("nodeSetSelected("+b+")",a),!c.unselectable){if(c.selected&&b||!c.selected&&!b)return!!c.selected;if(this._triggerNodeEvent("beforeSelect",c,a.originalEvent)===!1)return!!c.selected;b&&1===e.selectMode?d.lastSelectedNode&&d.lastSelectedNode.setSelected(!1):3===e.selectMode&&(c.selected=b,c.fixSelection3AfterClick()),c.selected=b,this.nodeRenderStatus(a),d.lastSelectedNode=b?c:null,d._triggerNodeEvent("select",a)}},nodeSetStatus:function(b,c,d,e){function f(){var a=h.children?h.children[0]:null;if(a&&a.isStatusNode()){try{h.ul&&(h.ul.removeChild(a.li),a.li=null)}catch(b){}1===h.children.length?h.children=[]:h.children.shift()}}function g(b,c){var d=h.children?h.children[0]:null;return d&&d.isStatusNode()?(a.extend(d,b),d.statusNodeType=c,i._callHook("nodeRender",d),i._callHook("nodeRenderTitle",d)):(b.key="_statusNode",h._setChildren([b]),h.children[0].statusNodeType=c,i.render()),h.children[0]}var h=b.node,i=b.tree;switch(c){case"ok":f(),h._isLoading=!1,h._error=null,h.renderStatus();break;case"loading":h.parent||g({title:i.options.strings.loading+(d?" ("+d+") ":""),tooltip:e,extraClasses:"fancytree-statusnode-wait"},c),h._isLoading=!0,h._error=null,h.renderStatus();break;case"error":g({title:i.options.strings.loadError+(d?" ("+d+") ":""),tooltip:e,extraClasses:"fancytree-statusnode-error"},c),h._isLoading=!1,h._error={message:d,details:e},h.renderStatus();break;default:a.error("invalid node status "+c)}},nodeToggleExpanded:function(a){return this.nodeSetExpanded(a,!a.node.expanded)},nodeToggleSelected:function(a){return this.nodeSetSelected(a,!a.node.selected)},treeClear:function(a){var b=a.tree;b.activeNode=null,b.focusNode=null,b.$div.find(">ul.fancytree-container").empty(),b.rootNode.children=null},treeCreate:function(){},treeDestroy:function(){},treeInit:function(a){this.treeLoad(a)},treeLoad:function(b,c){var d,f,g,h=b.tree,i=b.widget.element,j=a.extend({},b,{node:this.rootNode});if(h.rootNode.children&&this.treeClear(b),c=c||this.options.source)"string"==typeof c&&e();else switch(d=i.data("type")||"html"){case"html":f=i.find(">ul:first"),f.addClass("ui-fancytree-source ui-helper-hidden"),c=a.ui.fancytree.parseHtml(f),this.data=a.extend(this.data,o(f));break;case"json":c=a.parseJSON(i.text()),c.children&&(c.title&&(h.title=c.title),c=c.children);break;default:a.error("Invalid data-type: "+d)}return g=this.nodeLoadChildren(j,c).done(function(){h.render(),3===b.options.selectMode&&h.rootNode.fixSelection3FromEndNodes(),h._triggerTreeEvent("init",!0)}).fail(function(){h.render(),h._triggerTreeEvent("init",!1)})},treeRegisterNode:function(){},treeSetFocus:function(a,b){b=b!==!1,b!==this.hasFocus()&&(this._hasFocus=b,this.$container.toggleClass("fancytree-treefocus",b),this._triggerTreeEvent(b?"focusTree":"blurTree"))}}),a.widget("ui.fancytree",{options:{activeVisible:!0,ajax:{type:"GET",cache:!1,dataType:"json"},aria:!1,autoActivate:!0,autoCollapse:!1,autoScroll:!1,checkbox:!1,clickFolderMode:4,debugLevel:null,disabled:!1,enableAspx:!0,extensions:[],fx:{height:"toggle",duration:200},generateIds:!1,icons:!0,id:null,idPrefix:"ft_",keyboard:!0,keyPathSeparator:"/",minExpandLevel:1,scrollOfs:{top:0,bottom:0},scrollParent:null,selectMode:2,strings:{loading:"Loading…",loadError:"Load error!"},tabbable:!0,titlesTabbable:!1,_classNames:{node:"fancytree-node",folder:"fancytree-folder",combinedExpanderPrefix:"fancytree-exp-",combinedIconPrefix:"fancytree-ico-",hasChildren:"fancytree-has-children",active:"fancytree-active",selected:"fancytree-selected",expanded:"fancytree-expanded",lazy:"fancytree-lazy",focused:"fancytree-focused",partsel:"fancytree-partsel",lastsib:"fancytree-lastsib",loading:"fancytree-loading",error:"fancytree-error"},lazyLoad:null,postProcess:null},_create:function(){this.tree=new r(this),this.$source=this.source||"json"===this.element.data("type")?this.element:this.element.find(">ul:first");var b,c,e,g=this.options.extensions,h=this.tree;for(e=0;e"),d&&a.Widget.prototype._setOption.apply(this,arguments),e&&this.tree.render(!0,!1)},destroy:function(){this._unbind(),this.tree._callHook("treeDestroy",this.tree),this.tree.$div.find(">ul.fancytree-container").remove(),this.$source&&this.$source.removeClass("ui-helper-hidden"),a.Widget.prototype.destroy.call(this)},_unbind:function(){var b=this.tree._ns;this.element.unbind(b),this.tree.$container.unbind(b),a(c).unbind(b)},_bind:function(){var a=this,b=this.options,c=this.tree,d=c._ns;this._unbind(),c.$container.on("focusin"+d+" focusout"+d,function(a){var b=t.getNode(a),d="focusin"===a.type;b?c._callHook("nodeSetFocus",b,d):c._callHook("treeSetFocus",c,d)}).on("selectstart"+d,"span.fancytree-title",function(a){a.preventDefault()}).on("keydown"+d,function(a){if(b.disabled||b.keyboard===!1)return!0;var d,e=c.focusNode,f=c._makeHookContext(e||c,a),g=c.phase;try{return c.phase="userEvent",d=e?c._triggerNodeEvent("keydown",e,a):c._triggerTreeEvent("keydown",a),"preventNav"===d?d=!0:d!==!1&&(d=c._callHook("nodeKeydown",f)),d}finally{c.phase=g}}).on("click"+d+" dblclick"+d,function(c){if(b.disabled)return!0;var d,e=t.getEventTarget(c),f=e.node,g=a.tree,h=g.phase;if(!f)return!0;d=g._makeHookContext(f,c);try{switch(g.phase="userEvent",c.type){case"click":return d.targetType=e.type,g._triggerNodeEvent("click",d,c)===!1?!1:g._callHook("nodeClick",d);case"dblclick":return d.targetType=e.type,g._triggerNodeEvent("dblclick",d,c)===!1?!1:g._callHook("nodeDblclick",d)}}finally{g.phase=h}})},getActiveNode:function(){return this.tree.activeNode},getNodeByKey:function(a){return this.tree.getNodeByKey(""+a)},getRootNode:function(){return this.tree.rootNode},getTree:function(){return this.tree}}),t=a.ui.fancytree,a.extend(a.ui.fancytree,{version:"2.4.1",buildType: "production",debugLevel: 1,_nextId:1,_nextNodeKey:1,_extensions:{},_FancytreeClass:r,_FancytreeNodeClass:q,jquerySupports:{positionMyOfs:i(a.ui.version,1,9)},assert:function(a,b){return f(a,b)},debounce:function(a,b,c,d){var e;return 3===arguments.length&&"boolean"!=typeof c&&(d=c,c=!1),function(){var f=arguments;d=d||this,c&&!e&&b.apply(d,f),clearTimeout(e),e=setTimeout(function(){c||b.apply(d,f),e=null},a)}},debug:function(){a.ui.fancytree.debugLevel>=2&&g("log",arguments)},error:function(){g("error",arguments)},escapeHtml:function(a){return(""+a).replace(/[&<>"'\/]/g,function(a){return u[a]})},unescapeHtml:function(a){var b=c.createElement("div");return b.innerHTML=a,0===b.childNodes.length?"":b.childNodes[0].nodeValue},getEventTargetType:function(a){return this.getEventTarget(a).type},getEventTarget:function(b){var c=b&&b.target?b.target.className:"",e={node:this.getNode(b.target),type:d};return/\bfancytree-title\b/.test(c)?e.type="title":/\bfancytree-expander\b/.test(c)?e.type=e.node.hasChildren()===!1?"prefix":"expander":/\bfancytree-checkbox\b/.test(c)||/\bfancytree-radio\b/.test(c)?e.type="checkbox":/\bfancytree-icon\b/.test(c)?e.type="icon":/\bfancytree-node\b/.test(c)?e.type="title":b&&b.target&&a(b.target).closest(".fancytree-title").length&&(e.type="title"),e},getNode:function(a){if(a instanceof q)return a;for(a.selector!==d?a=a[0]:a.originalEvent!==d&&(a=a.target);a;){if(a.ftnode)return a.ftnode;a=a.parentNode}return null},info:function(){a.ui.fancytree.debugLevel>=1&&g("info",arguments)},parseHtml:function(b){var c,e,f,g,h,i,j,k,l=b.find(">li"),m=[];return l.each(function(){var l,n=a(this),p=n.find(">span:first",this),q=p.length?null:n.find(">a:first"),r={tooltip:null,data:{}};for(p.length?r.title=p.html():q&&q.length?(r.title=q.html(),r.data.href=q.attr("href"),r.data.target=q.attr("target"),r.tooltip=q.attr("title")):(r.title=n.html(),g=r.title.search(/
      =0&&(r.title=r.title.substring(0,g))),r.title=a.trim(r.title),e=0,f=v.length;f>e;e++)r[v[e]]=d;for(j=this.className.split(" "),c=[],e=0,f=j.length;f>e;e++)k=j[e],w[k]?r[k]=!0:c.push(k);if(r.extraClasses=c.join(" "),h=n.attr("title"),h&&(r.tooltip=h),h=n.attr("id"),h&&(r.key=h),l=o(n),l&&!a.isEmptyObject(l)){for(e=0,f=x.length;f>e;e++)h=x[e],i=l[h],null!=i&&(delete l[h],r[h]=i);a.extend(r.data,l)}b=n.find(">ul:first"),r.children=b.length?a.ui.fancytree.parseHtml(b):r.lazy?d:null,m.push(r)}),m},registerExtension:function(b){f(null!=b.name,"extensions must have a `name` property."),f(null!=b.version,"extensions must have a `version` property."),a.ui.fancytree._extensions[b.name]=b},warn:function(){g("warn",arguments)}})}(jQuery,window,document); + +/*! Extension 'jquery.fancytree.childcounter.min.js' */ +!function(a){"use strict";a.ui.fancytree._FancytreeClass.prototype.countSelected=function(a){{var b=this;b.options}return b.getSelectedNodes(a).length},a.ui.fancytree._FancytreeNodeClass.prototype.toUpper=function(){var a=this;return a.setTitle(a.title.toUpperCase())},a.ui.fancytree.prototype.widgetMethod1=function(a){this.tree;return a},a.ui.fancytree.registerExtension({name:"childcounter",version:"1.0.0",options:{deep:!0,hideZeros:!0,hideExpanded:!1},foo:42,_appendCounter:function(){},treeInit:function(a){a.options,a.options.childcounter;this._super(a),this.$container.addClass("fancytree-ext-childcounter")},treeDestroy:function(a){this._super(a)},nodeRenderTitle:function(b,c){var d=b.node,e=b.options.childcounter,f=null==d.data.childCounter?d.countChildren(e.deep):+d.data.childCounter;this._super(b,c),!f&&e.hideZeros||d.isExpanded()&&e.hideExpanded||a("span.fancytree-icon",d.span).append(a("").text(f))},nodeSetExpanded:function(a,b,c){{var d=a.tree;a.node}return this._super(a,b,c).always(function(){d.nodeRenderTitle(a)})}})}(jQuery); + +/*! Extension 'jquery.fancytree.clones.min.js' */ +!function(a){"use strict";function b(a,b){var c;for(c=a.length-1;c>=0;c--)if(a[c]===b)return a.splice(c,1),!0;return!1}function c(a,b,c){for(var d,e,f=3&a.length,g=a.length-f,h=c,i=3432918353,j=461845907,k=0;g>k;)e=255&a.charCodeAt(k)|(255&a.charCodeAt(++k))<<8|(255&a.charCodeAt(++k))<<16|(255&a.charCodeAt(++k))<<24,++k,e=(65535&e)*i+(((e>>>16)*i&65535)<<16)&4294967295,e=e<<15|e>>>17,e=(65535&e)*j+(((e>>>16)*j&65535)<<16)&4294967295,h^=e,h=h<<13|h>>>19,d=5*(65535&h)+((5*(h>>>16)&65535)<<16)&4294967295,h=(65535&d)+27492+(((d>>>16)+58964&65535)<<16);switch(e=0,f){case 3:e^=(255&a.charCodeAt(k+2))<<16;case 2:e^=(255&a.charCodeAt(k+1))<<8;case 1:e^=255&a.charCodeAt(k),e=(65535&e)*i+(((e>>>16)*i&65535)<<16)&4294967295,e=e<<15|e>>>17,e=(65535&e)*j+(((e>>>16)*j&65535)<<16)&4294967295,h^=e}return h^=a.length,h^=h>>>16,h=2246822507*(65535&h)+((2246822507*(h>>>16)&65535)<<16)&4294967295,h^=h>>>13,h=3266489909*(65535&h)+((3266489909*(h>>>16)&65535)<<16)&4294967295,h^=h>>>16,b?("0000000"+(h>>>0).toString(16)).substr(-8):h>>>0}function d(b){var d,e=a.map(b.getParentList(!1,!0),function(a){return a.refKey||a.key});return e=e.join("/"),d="id_"+c(e,!0),b.debug(e+" -> "+d),d}var e=a.ui.fancytree.assert;a.ui.fancytree._FancytreeNodeClass.prototype.getCloneList=function(b){var c,d=this.tree,e=d.refMap[this.refKey]||null,f=d.keyMap;return e&&(c=this.key,b?e=a.map(e,function(a){return f[a]}):(e=a.map(e,function(a){return a===c?null:f[a]}),e.length<1&&(e=null))),e},a.ui.fancytree._FancytreeNodeClass.prototype.isClone=function(){var a=this.refKey||null,b=a&&this.tree.refMap[a]||null;return!!(b&&b.length>1)},a.ui.fancytree._FancytreeNodeClass.prototype.reRegister=function(b,c){b=null==b?null:""+b,c=null==c?null:""+c,this.debug("reRegister",b,c);var d=this.tree,e=this.key,f=this.refKey,g=d.keyMap,h=d.refMap,i=h[f]||null,j=!1;return null!=b&&b!==this.key&&(g[b]&&a.error("[ext-clones] reRegister("+b+"): already exists: "+this),delete g[e],g[b]=this,i&&(h[f]=a.map(i,function(a){return a===e?b:a})),this.key=b,j=!0),null!=c&&c!==this.refKey&&(i&&(1===i.length?delete h[f]:h[f]=a.map(i,function(a){return a===e?null:a})),h[c]?h[c].append(b):h[c]=[this.key],this.refKey=c,j=!0),j},a.ui.fancytree._FancytreeClass.prototype.getNodesByRef=function(b,c){var d=this.keyMap,e=this.refMap[b]||null;return e&&(e=c?a.map(e,function(a){var b=d[a];return b.isDescendantOf(c)?b:null}):a.map(e,function(a){return d[a]}),e.length<1&&(e=null)),e},a.ui.fancytree._FancytreeClass.prototype.changeRefKey=function(a,b){var c,d,e=this.keyMap,f=this.refMap[a]||null;if(f){for(c=0;c",k[m]))):(null==j[l]&&a.error("clones.treeRegisterNode: node.key not registered: "+f.key),delete j[l],m&&(g=k[m],f.debug("clones.treeRegisterNode: remove clone BEFORE =>",k[m]),g&&(h=g.length,1>=h?(e(1===h),e(g[0]===l),delete k[m]):(b(g,l),2===h&&c.options.clones.highlightClones&&j[g[0]].renderStatus()),f.debug("clones.treeRegisterNode: remove clone =>",k[m])))),this._super(c,d,f))},nodeRenderStatus:function(b){var c,d,e=b.node;return d=this._super(b),b.options.clones.highlightClones&&(c=a(e[b.tree.statusClassPropName]),c.length&&e.isClone()&&c.addClass("fancytree-clone")),d},nodeSetActive:function(b,c){var d,e=b.tree.statusClassPropName,f=b.node;return d=this._super(b,c),b.options.clones.highlightActiveClones&&f.isClone()&&a.each(f.getCloneList(!0),function(b,d){d.debug("clones.nodeSetActive: ",c!==!1),a(d[e]).toggleClass("fancytree-active-clone",c!==!1)}),d}})}(jQuery,window,document); + +/*! Extension 'jquery.fancytree.dnd.min.js' */ +!function(a,b,c,d){"use strict";function e(a){return 0===a?"":a>0?"+"+a:""+a}function f(b){var c=b.options.dnd||null;c&&g(),c&&c.dragStart&&b.widget.element.draggable(a.extend({addClasses:!1,appendTo:"body",containment:!1,delay:0,distance:4,revert:!1,scroll:!0,scrollSpeed:7,scrollSensitivity:10,connectToFancytree:!0,helper:function(b){var c=a.ui.fancytree.getNode(b.target);return c?c.tree.ext.dnd._onDragEvent("helper",c,null,b,null,null):"
      ERROR?: helper requested but sourceNode not found
      "},start:function(a,b){var c=b.helper.data("ftSourceNode");return!!c}},b.options.dnd.draggable)),c&&c.dragDrop&&b.widget.element.droppable(a.extend({addClasses:!1,tolerance:"intersect",greedy:!1},b.options.dnd.droppable))}function g(){i||(a.ui.plugin.add("draggable","connectToFancytree",{start:function(b,c){var d=a(this).data("ui-draggable")||a(this).data("draggable"),e=c.helper.data("ftSourceNode")||null;return e?(d.offset.click.top=-2,d.offset.click.left=16,e.tree.ext.dnd._onDragEvent("start",e,null,b,c,d)):void 0},drag:function(b,c){var d,e=a(this).data("ui-draggable")||a(this).data("draggable"),f=c.helper.data("ftSourceNode")||null,g=c.helper.data("ftTargetNode")||null,i=a.ui.fancytree.getNode(b.target);return b.target&&!i&&(d=a(b.target).closest("div.fancytree-drag-helper,#fancytree-drop-marker").length>0)?void h("Drag event over helper: ignored."):(c.helper.data("ftTargetNode",i),g&&g!==i&&g.tree.ext.dnd._onDragEvent("leave",g,f,b,c,e),void(i&&i.tree.options.dnd.dragDrop&&(i===g?i.tree.ext.dnd._onDragEvent("over",i,f,b,c,e):i.tree.ext.dnd._onDragEvent("enter",i,f,b,c,e))))},stop:function(b,c){var d=a(this).data("ui-draggable")||a(this).data("draggable"),e=c.helper.data("ftSourceNode")||null,f=c.helper.data("ftTargetNode")||null,g=b.type,i="mouseup"===g&&1===b.which;i||h("Drag was cancelled"),f&&(i&&f.tree.ext.dnd._onDragEvent("drop",f,e,b,c,d),f.tree.ext.dnd._onDragEvent("leave",f,e,b,c,d)),e&&e.tree.ext.dnd._onDragEvent("stop",e,null,b,c,d)}}),i=!0)}var h=a.ui.fancytree.debug,i=!1;a.ui.fancytree.registerExtension({name:"dnd",version:"0.1.0",options:{dragStart:null,dragStop:null,autoExpandMS:1e3,preventVoidMoves:!0,preventRecursiveMoves:!0,focusOnClick:!1,dragEnter:null,dragOver:null,dragDrop:null,dragLeave:null,draggable:null,droppable:null},treeInit:function(b){var c=b.tree;this._super(b),c.options.dnd.dragStart&&c.$container.on("mousedown",function(d){if(!c.hasFocus()&&b.options.dnd.focusOnClick){var e=a.ui.fancytree.getNode(d);e.debug("Re-enable focus that was prevented by jQuery UI draggable."),a(d.target).closest(":tabbable").focus()}}),f(c)},nodeKeydown:function(b){var c=b.originalEvent;return c.which===a.ui.keyCode.ESCAPE&&this._local._cancelDrag(),this._super(b)},nodeClick:function(a){return this._super(a)},_setDndStatus:function(b,c,d,f,g){var h,i=0,j="center",k=this._local,l=b?a(b.span):null,m=a(c.span);if(k.$dropMarker||(k.$dropMarker=a("
      ").hide().css({"z-index":1e3}).prependTo(a(this.$div).parent())),"after"===f||"before"===f||"over"===f){switch(f){case"before":k.$dropMarker.removeClass("fancytree-drop-after fancytree-drop-over").addClass("fancytree-drop-before"),j="top";break;case"after":k.$dropMarker.removeClass("fancytree-drop-before fancytree-drop-over").addClass("fancytree-drop-after"),j="bottom";break;default:k.$dropMarker.removeClass("fancytree-drop-after fancytree-drop-before").addClass("fancytree-drop-over"),m.addClass("fancytree-drop-target"),i=8}h=a.ui.fancytree.jquerySupports.positionMyOfs?{my:"left"+e(i)+" center",at:"left "+j,of:m}:{my:"left center",at:"left "+j,of:m,offset:""+i+" 0"},k.$dropMarker.show().position(h)}else m.removeClass("fancytree-drop-target"),k.$dropMarker.hide();"after"===f?m.addClass("fancytree-drop-after"):m.removeClass("fancytree-drop-after"),"before"===f?m.addClass("fancytree-drop-before"):m.removeClass("fancytree-drop-before"),g===!0?(l&&l.addClass("fancytree-drop-accept"),m.addClass("fancytree-drop-accept"),d.addClass("fancytree-drop-accept")):(l&&l.removeClass("fancytree-drop-accept"),m.removeClass("fancytree-drop-accept"),d.removeClass("fancytree-drop-accept")),g===!1?(l&&l.addClass("fancytree-drop-reject"),m.addClass("fancytree-drop-reject"),d.addClass("fancytree-drop-reject")):(l&&l.removeClass("fancytree-drop-reject"),m.removeClass("fancytree-drop-reject"),d.removeClass("fancytree-drop-reject"))},_onDragEvent:function(b,c,e,f,g,i){"over"!==b&&h("tree.ext.dnd._onDragEvent(%s, %o, %o) - %o",b,c,e,this);var j,k,l,m,n,o,p,q=this.options,r=q.dnd,s=this._makeHookContext(c,f,{otherNode:e,ui:g,draggable:i}),t=null,u=a(c.span);switch(b){case"helper":j=a("
      ").css({zIndex:3,position:"relative"}).append(u.find("span.fancytree-title").clone()),a("ul.fancytree-container",c.tree.$div).append(j),j.data("ftSourceNode",c),t=j;break;case"start":c.isStatusNode()?t=!1:r.dragStart&&(t=r.dragStart(c,s)),t===!1?(this.debug("tree.dragStart() cancelled"),g.helper.trigger("mouseup").hide()):u.addClass("fancytree-drag-source");break;case"enter":p=r.preventRecursiveMoves&&c.isDescendantOf(e)?!1:r.dragEnter?r.dragEnter(c,s):null,t=p?a.isArray(p)?{over:a.inArray("over",p)>=0,before:a.inArray("before",p)>=0,after:a.inArray("after",p)>=0}:{over:p===!0||"over"===p,before:p===!0||"before"===p,after:p===!0||"after"===p}:!1,g.helper.data("enterResponse",t),h("helper.enterResponse: %o",t);break;case"over":n=g.helper.data("enterResponse"),o=null,n===!1||("string"==typeof n?o=n:(k=u.offset(),l={x:f.pageX-k.left,y:f.pageY-k.top},m={x:l.x/u.width(),y:l.y/u.height()},n.after&&m.y>.75?o="after":!n.over&&n.after&&m.y>.5?o="after":n.before&&m.y<=.25?o="before":!n.over&&n.before&&m.y<=.5?o="before":n.over&&(o="over"),r.preventVoidMoves&&(c===e?(h(" drop over source node prevented"),o=null):"before"===o&&e&&c===e.getNextSibling()?(h(" drop after source node prevented"),o=null):"after"===o&&e&&c===e.getPrevSibling()?(h(" drop before source node prevented"),o=null):"over"===o&&e&&e.parent===c&&e.isLastSibling()&&(h(" drop last child over own parent prevented"),o=null)),g.helper.data("hitMode",o))),"over"===o&&r.autoExpandMS&&c.hasChildren()!==!1&&!c.expanded&&c.scheduleAction("expand",r.autoExpandMS),o&&r.dragOver&&(s.hitMode=o,t=r.dragOver(c,s)),this._local._setDndStatus(e,c,g.helper,o,t!==!1&&null!==o);break;case"drop":o=g.helper.data("hitMode"),o&&r.dragDrop&&(s.hitMode=o,r.dragDrop(c,s));break;case"leave":c.scheduleAction("cancel"),g.helper.data("enterResponse",null),g.helper.data("hitMode",null),this._local._setDndStatus(e,c,g.helper,"out",d),r.dragLeave&&r.dragLeave(c,s);break;case"stop":u.removeClass("fancytree-drag-source"),r.dragStop&&r.dragStop(c,s);break;default:a.error("Unsupported drag event: "+b)}return t},_cancelDrag:function(){var b=a.ui.ddmanager.current;b&&b.cancel()}})}(jQuery,window,document); + +/*! Extension 'jquery.fancytree.edit.min.js' */ +!function(a,b,c){"use strict";var d=/Mac/.test(navigator.platform),e=a.ui.fancytree.escapeHtml,f=a.ui.fancytree.unescapeHtml;a.ui.fancytree._FancytreeNodeClass.prototype.editStart=function(){var b,d=this,e=this.tree,g=e.ext.edit,h=e.options.edit,i=a(".fancytree-title",d.span),j={node:d,tree:e,options:e.options,isNew:a(d.span).hasClass("fancytree-edit-new"),orgTitle:d.title,input:null,dirty:!1};return a.ui.fancytree.assert(!g.currentNode,"recursive edit"),g.currentNode=this,g.eventData=j,h.beforeEdit.call(d,{type:"beforeEdit"},j)===!1?!1:(e.widget._unbind(),a(c).on("mousedown.fancytree-edit",function(b){a(b.target).hasClass("fancytree-edit-input")||d.editEnd(!0,b)}),b=a("",{"class":"fancytree-edit-input",value:f(j.orgTitle)}),g.eventData.input=b,null!=h.adjustWidthOfs&&b.width(i.width()+h.adjustWidthOfs),null!=h.inputCss&&b.css(h.inputCss),i.html(b),b.focus().change(function(){b.addClass("fancytree-edit-dirty")}).keydown(function(b){switch(b.which){case a.ui.keyCode.ESCAPE:d.editEnd(!1,b);break;case a.ui.keyCode.ENTER:return d.editEnd(!0,b),!1}b.stopPropagation()}).blur(function(a){return d.editEnd(!0,a)}),void h.edit.call(d,{type:"edit"},j))},a.ui.fancytree._FancytreeNodeClass.prototype.editEnd=function(b){var d,f=this,g=this.tree,h=g.ext.edit,i=h.eventData,j=g.options.edit,k=a(".fancytree-title",f.span),l=k.find("input.fancytree-edit-input");return j.trim&&l.val(a.trim(l.val())),d=l.val(),i.dirty=d!==f.title,i.save=b===!1?!1:i.isNew?""!==d:i.dirty&&""!==d,j.beforeClose.call(f,{type:"beforeClose"},i)===!1?!1:i.save&&j.save.call(f,{type:"save"},i)===!1?!1:(l.removeClass("fancytree-edit-dirty").unbind(),a(c).off(".fancytree-edit"),i.save?(f.setTitle(e(d)),f.setFocus()):i.isNew?(f.remove(),f=i.node=null,h.relatedNode.setFocus()):(f.renderTitle(),f.setFocus()),h.eventData=null,h.currentNode=null,h.relatedNode=null,g.widget._bind(),a(g.$container).focus(),i.input=null,j.close.call(f,{type:"close"},i),!0)},a.ui.fancytree._FancytreeNodeClass.prototype.editCreateNode=function(b,c){var d,e=this;return b=b||"child",null==c?c={title:""}:"string"==typeof c?c={title:c}:a.ui.fancytree.assert(a.isPlainObject(c)),"child"!==b||this.isExpanded()||this.hasChildren()===!1?(d=this.addNode(c,b),d.makeVisible(),a(d.span).addClass("fancytree-edit-new"),this.tree.ext.edit.relatedNode=this,void d.editStart()):void this.setExpanded().done(function(){e.editCreateNode(b,c)})},a.ui.fancytree._FancytreeClass.prototype.isEditing=function(){return this.ext.edit.currentNode},a.ui.fancytree._FancytreeNodeClass.prototype.isEditing=function(){return this.tree.ext.edit.currentNode===this},a.ui.fancytree.registerExtension({name:"edit",version:"0.2.0",options:{adjustWidthOfs:4,allowEmpty:!1,inputCss:{minWidth:"3em"},triggerCancel:["esc","tab","click"],triggerStart:["f2","shift+click","mac+enter"],trim:!0,beforeClose:a.noop,beforeEdit:a.noop,close:a.noop,edit:a.noop,save:a.noop},currentNode:null,treeInit:function(a){this._super(a),this.$container.addClass("fancytree-ext-edit")},nodeClick:function(b){return a.inArray("shift+click",b.options.edit.triggerStart)>=0&&b.originalEvent.shiftKey?(b.node.editStart(),!1):this._super(b)},nodeDblclick:function(b){return a.inArray("dblclick",b.options.edit.triggerStart)>=0?(b.node.editStart(),!1):this._super(b)},nodeKeydown:function(b){switch(b.originalEvent.which){case 113:if(a.inArray("f2",b.options.edit.triggerStart)>=0)return b.node.editStart(),!1;break;case a.ui.keyCode.ENTER:if(a.inArray("mac+enter",b.options.edit.triggerStart)>=0&&d)return b.node.editStart(),!1}return this._super(b)}})}(jQuery,window,document); + +/*! Extension 'jquery.fancytree.filter.min.js' */ +!function(a){"use strict";function b(a){return(a+"").replace(/([.?*+\^\$\[\]\\(){}|-])/g,"\\$1")}a.ui.fancytree._FancytreeClass.prototype._applyFilterImpl=function(a,c,d){var e,f,g=0,h="hide"===this.options.filter.mode;return d=!!d&&!c,"string"==typeof a&&(e=b(a),f=new RegExp(".*"+e+".*","i"),a=function(a){return!!f.exec(a.title)}),this.enableFilter=!0,this.$div.addClass("fancytree-ext-filter"),this.$div.addClass(h?"fancytree-ext-filter-hide":"fancytree-ext-filter-dimm"),this.visit(function(a){delete a.match,delete a.subMatch}),this.visit(function(b){return d&&null!=b.children||!a(b)||(g++,b.match=!0,b.visitParents(function(a){a.subMatch=!0}),!c)?void 0:(b.visit(function(a){a.match=!0}),"skip")}),this.render(),g},a.ui.fancytree._FancytreeClass.prototype.filterNodes=function(a,b){return this._applyFilterImpl(a,!1,b)},a.ui.fancytree._FancytreeClass.prototype.applyFilter=function(){return this.warn("Fancytree.applyFilter() is deprecated since 2014-05-10. Use .filterNodes() instead."),this.filterNodes.apply(this,arguments)},a.ui.fancytree._FancytreeClass.prototype.filterBranches=function(a){return this._applyFilterImpl(a,!0,null)},a.ui.fancytree._FancytreeClass.prototype.clearFilter=function(){this.visit(function(a){delete a.match,delete a.subMatch}),this.enableFilter=!1,this.$div.removeClass("fancytree-ext-filter fancytree-ext-filter-dimm fancytree-ext-filter-hide"),this.render()},a.ui.fancytree.registerExtension({name:"filter",version:"0.2.0",options:{mode:"dimm"},treeInit:function(a){this._super(a)},nodeRenderStatus:function(b){var c,d=b.node,e=b.tree,f=a(d[e.statusClassPropName]);return c=this._super(b),f.length&&e.enableFilter?(f.toggleClass("fancytree-match",!!d.match).toggleClass("fancytree-submatch",!!d.subMatch).toggleClass("fancytree-hide",!(d.match||d.subMatch)),c):c}})}(jQuery,window,document); + +/*! Extension 'jquery.fancytree.glyph.min.js' */ +!function(a){"use strict";function b(a,b){return a.map[b]}a.ui.fancytree.registerExtension({name:"glyph",version:"0.2.0",options:{map:{checkbox:"icon-check-empty",checkboxSelected:"icon-check",checkboxUnknown:"icon-check icon-muted",error:"icon-exclamation-sign",expanderClosed:"icon-caret-right",expanderLazy:"icon-angle-right",expanderOpen:"icon-caret-down",doc:"icon-file-alt",noExpander:"",docOpen:"icon-file-alt",loading:"icon-refresh icon-spin",folder:"icon-folder-close-alt",folderOpen:"icon-folder-open-alt"}},treeInit:function(a){var b=a.tree;this._super(a),b.$container.addClass("fancytree-ext-glyph")},nodeRenderStatus:function(c){var d,e,f=c.node,g=a(f.span),h=c.options.glyph,i=h.map;this._super(c),f.isRoot()||(e=g.children("span.fancytree-expander").get(0),e&&(d=f.isLoading()?"loading":f.expanded?"expanderOpen":f.isUndefined()?"expanderLazy":f.hasChildren()?"expanderClosed":"noExpander",e.className="fancytree-expander "+i[d]),e=f.tr?a("td",f.tr).children("span.fancytree-checkbox").get(0):g.children("span.fancytree-checkbox").get(0),e&&(d=f.selected?"checkboxSelected":f.partsel?"checkboxUnknown":"checkbox",e.className="fancytree-checkbox "+i[d]),e=g.children("span.fancytree-icon").get(0),e&&(d=f.folder?f.expanded?b(h,"folderOpen"):b(h,"folder"):f.expanded?b(h,"docOpen"):b(h,"doc"),e.className="fancytree-icon "+d))},nodeSetStatus:function(c,d,e,f){var g,h=c.options.glyph,i=c.node;this._super(c,d,e,f),g=i.parent?a("span.fancytree-expander",i.span).get(0):a(".fancytree-statusnode-wait, .fancytree-statusnode-error",i[this.nodeContainerAttrName]).find("span.fancytree-expander").get(0),"loading"===d?g.className="fancytree-expander "+b(h,"loading"):"error"===d&&(g.className="fancytree-expander "+b(h,"error"))}})}(jQuery,window,document); + +/*! Extension 'jquery.fancytree.gridnav.min.js' */ +!function(a){"use strict";function b(b,c){var d,e=c.get(0),f=0;return b.children().each(function(){return this===e?!1:(d=a(this).prop("colspan"),void(f+=d?d:1))}),f}function c(b,c){var d,e=null,f=0;return b.children().each(function(){return f>=c?(e=a(this),!1):(d=a(this).prop("colspan"),void(f+=d?d:1))}),e}function d(a,d){var f,g,h=a.closest("td"),i=null;switch(d){case e.LEFT:i=h.prev();break;case e.RIGHT:i=h.next();break;case e.UP:case e.DOWN:for(f=h.parent(),g=b(f,h);;){if(f=d===e.UP?f.prev():f.next(),!f.length)break;if(!f.is(":hidden")&&(i=c(f,g),i&&i.find(":input").length))break}}return i}var e=a.ui.keyCode,f={text:[e.UP,e.DOWN],checkbox:[e.UP,e.DOWN,e.LEFT,e.RIGHT],radiobutton:[e.UP,e.DOWN,e.LEFT,e.RIGHT],"select-one":[e.LEFT,e.RIGHT],"select-multiple":[e.LEFT,e.RIGHT]};a.ui.fancytree.registerExtension({name:"gridnav",version:"0.0.1",options:{autofocusInput:!1,handleCursorKeys:!0},treeInit:function(b){this._requireExtension("table",!0,!0),this._super(b),this.$container.addClass("fancytree-ext-gridnav"),this.$container.on("focusin",function(c){var d,e=a.ui.fancytree.getNode(c.target);e&&!e.isActive()&&(d=b.tree._makeHookContext(e,c),b.tree._callHook("nodeSetActive",d,!0))})},nodeSetActive:function(b,c){var d,e=b.options.gridnav,f=b.node,g=b.originalEvent||{},h=a(g.target).is(":input");c=c!==!1,this._super(b,c),c&&(b.options.titlesTabbable?(h||(a(f.span).find("span.fancytree-title").focus(),f.setFocus()),b.tree.$container.attr("tabindex","-1")):e.autofocusInput&&!h&&(d=a(f.tr||f.span),d.find(":input:enabled:first").focus()))},nodeKeydown:function(b){var c,e,g,h=b.options.gridnav,i=b.originalEvent,j=a(i.target);return c=j.is(":input:enabled")?j.prop("type"):null,c&&h.handleCursorKeys?(e=f[c],e&&a.inArray(i.which,e)>=0&&(g=d(j,i.which),g&&g.length)?(g.find(":input:enabled").focus(),!1):!0):(b.tree.debug("ext-gridnav NOT HANDLED",i,c),this._super(b))}})}(jQuery,window,document); + +/*! Extension 'jquery.fancytree.persist.min.js' */ +!function(a,b,c,d){"use strict";function e(b,c,d,f,g){var i,j,k,l,m=!1,n=[],o=[];for(d=d||[],g=g||a.Deferred(),i=0,k=d.length;k>i;i++)j=d[i],l=b.getNodeByKey(j),l?f&&l.isUndefined()?(m=!0,b.debug("_loadLazyNodes: "+l+" is lazy: loading..."),n.push("expand"===f?l.setExpanded():l.load())):(b.debug("_loadLazyNodes: "+l+" already loaded."),l.setExpanded()):(o.push(j),b.debug("_loadLazyNodes: "+l+" was not yet found."));return a.when.apply(a,n).always(function(){if(m&&o.length>0)e(b,c,o,f,g);else{if(o.length)for(b.warn("_loadLazyNodes: could not load those keys: ",o),i=0,k=o.length;k>i;i++)j=d[i],c._appendKey(h,d[i],!1);g.resolve()}}),g}var f=a.ui.fancytree.assert,g="active",h="expanded",i="focus",j="selected";a.ui.fancytree._FancytreeClass.prototype.clearCookies=function(a){var b=this.ext.persist,c=b.cookiePrefix;a=a||"active expanded focus selected",a.indexOf(g)>=0&&b._data(c+g,null),a.indexOf(h)>=0&&b._data(c+h,null),a.indexOf(i)>=0&&b._data(c+i,null),a.indexOf(j)>=0&&b._data(c+j,null)},a.ui.fancytree._FancytreeClass.prototype.getPersistData=function(){var a=this.ext.persist,b=a.cookiePrefix,c=a.cookieDelimiter,d={};return d[g]=a._data(b+g),d[h]=(a._data(b+h)||"").split(c),d[j]=(a._data(b+j)||"").split(c),d[i]=a._data(b+i),d},a.ui.fancytree.registerExtension({name:"persist",version:"0.3.0",options:{cookieDelimiter:"~",cookiePrefix:d,cookie:{raw:!1,expires:"",path:"",domain:"",secure:!1},expandLazy:!1,overrideSource:!1,store:"auto",types:"active expanded focus selected"},_data:function(b,c){var e=this._local.localStorage;return c===d?e?e.getItem(b):a.cookie(b):void(null===c?e?e.removeItem(b):a.removeCookie(b):e?e.setItem(b,c):a.cookie(b,c,this.options.persist.cookie))},_appendKey:function(b,c,d){c=""+c;var e=this._local,f=this.options.persist,g=f.cookieDelimiter,h=e.cookiePrefix+b,i=e._data(h),j=i?i.split(g):[],k=a.inArray(c,j);k>=0&&j.splice(k,1),d&&j.push(c),e._data(h,j.join(g))},treeInit:function(k){var l=k.tree,m=k.options,n=this._local,o=this.options.persist;return f("localStore"===o.store||a.cookie,"Missing required plugin for 'persist' extension: jquery.cookie.js"),n.cookiePrefix=o.cookiePrefix||"fancytree-"+l._id+"-",n.storeActive=o.types.indexOf(g)>=0,n.storeExpanded=o.types.indexOf(h)>=0,n.storeSelected=o.types.indexOf(j)>=0,n.storeFocus=o.types.indexOf(i)>=0,n.localStorage="cookie"!==o.store&&b.localStorage?"local"===o.store?b.localStorage:b.sessionStorage:null,l.$div.bind("fancytreeinit",function(){var b,f,k,p,q,r=a.cookie(n.cookiePrefix+i);l.debug("COOKIE "+c.cookie),b=n._data(n.cookiePrefix+h),p=b&&b.split(o.cookieDelimiter),f=n.storeExpanded?e(l,n,p,o.expandLazy?"expand":!1,null):(new a.Deferred).resolve(),f.done(function(){if(n.storeSelected&&(b=n._data(n.cookiePrefix+j)))for(p=b.split(o.cookieDelimiter),k=0;k1&&h[0]!==b)for(c=a.inArray(b,h),e=h[c-1],g(e.tr);e.children&&(d=e.children[e.children.length-1],d.tr);)e=d;else e=f;return e}var g=a.ui.fancytree.assert;a.ui.fancytree.registerExtension({name:"table",version:"0.2.0",options:{checkboxColumnIdx:null,customStatus:!1,indentation:16,nodeColumnIdx:0},treeInit:function(b){var d,e,f,g=b.tree,h=g.widget.element;for(h.addClass("fancytree-container fancytree-ext-table"),g.tbody=h.find("> tbody")[0],g.columnCount=a("thead >tr >th",h).length,a(g.tbody).empty(),g.rowFragment=c.createDocumentFragment(),e=a(""),f="",b.options.aria&&(e.attr("role","row"),f=" role='gridcell'"),d=0;d":"");g.rowFragment.appendChild(e.get(0)),g.statusClassPropName="tr",g.ariaPropName="tr",this.nodeContainerAttrName="tr",this._super(b),a(g.rootNode.ul).remove(),g.rootNode.ul=null,g.$container=h,this.$container.attr("tabindex",this.options.tabbable?"0":"-1"),this.options.aria&&g.$container.attr("role","treegrid").attr("aria-readonly",!0)},nodeRemoveChildMarkup:function(b){var c=b.node;c.visit(function(b){b.tr&&(a(b.tr).remove(),b.tr=null)})},nodeRemoveMarkup:function(b){var c=b.node;c.tr&&(a(c.tr).remove(),c.tr=null),this.nodeRemoveChildMarkup(b)},nodeRender:function(b,c,h,i,j){var k,l,m,n,o,p,q,r,s=b.tree,t=b.node,u=b.options,v=!t.parent;if(j||(b.hasCollapsedParents=t.parent&&!t.parent.expanded),!v)if(t.tr)c?this.nodeRenderTitle(b):this.nodeRenderStatus(b);else{if(b.hasCollapsedParents)return void t.debug("nodeRender ignored due to unrendered parent");o=s.rowFragment.firstChild.cloneNode(!0),p=f(t),g(p),i===!0&&j?o.style.display="none":h&&b.hasCollapsedParents&&(o.style.display="none"),p.tr?d(p.tr,o):(g(!p.parent,"prev. row must have a tr, or is system root"),s.tbody.appendChild(o)),t.tr=o,t.key&&u.generateIds&&(t.tr.id=u.idPrefix+t.key),t.tr.ftnode=t,u.aria&&a(t.tr).attr("aria-labelledby","ftal_"+t.key),t.span=a("span.fancytree-node",t.tr).get(0),this.nodeRenderTitle(b),u.createNode&&u.createNode.call(s,{type:"createNode"},b)}if(u.renderNode&&u.renderNode.call(s,{type:"renderNode"},b),k=t.children,k&&(v||h||t.expanded))for(m=0,n=k.length;n>m;m++)r=a.extend({},b,{node:k[m]}),r.hasCollapsedParents=r.hasCollapsedParents||!t.expanded,this.nodeRender(r,c,h,i,!0);k&&!j&&(q=t.tr||null,l=s.tbody.firstChild,t.visit(function(a){if(a.tr){if(a.parent.expanded||"none"===a.tr.style.display||(a.tr.style.display="none",e(a,!1)),a.tr.previousSibling!==q){t.debug("_fixOrder: mismatch at node: "+a);var b=q?q.nextSibling:l;s.tbody.insertBefore(a.tr,b)}q=a.tr}}))},nodeRenderTitle:function(b){var c,d=b.node,e=b.options;this._super(b),e.checkbox&&null!=e.table.checkboxColumnIdx&&(c=a("span.fancytree-checkbox",d.span).detach(),a(d.tr).find("td:first").html(c)),d.isRoot()||this.nodeRenderStatus(b),!e.table.customStatus&&d.isStatusNode()||e.renderColumns&&e.renderColumns.call(b.tree,{type:"renderColumns"},b)},nodeRenderStatus:function(b){var c,d=b.node,e=b.options;this._super(b),a(d.tr).removeClass("fancytree-node"),c=(d.getLevel()-1)*e.table.indentation,a(d.span).css({marginLeft:c+"px"})},nodeSetExpanded:function(b,c,d){function f(a){c=c!==!1,e(b.node,c),a?c&&b.options.autoScroll&&!d.noAnimation&&b.node.hasChildren()?b.node.getLastChild().scrollIntoView(!0,{topNode:b.node}).always(function(){d.noEvents||b.tree._triggerNodeEvent(c?"expand":"collapse",b),g.resolveWith(b.node)}):(d.noEvents||b.tree._triggerNodeEvent(c?"expand":"collapse",b),g.resolveWith(b.node)):(d.noEvents||b.tree._triggerNodeEvent(c?"expand":"collapse",b),g.rejectWith(b.node))}var g=new a.Deferred,h=a.extend({},d,{noEvents:!0,noAnimation:!0});return d=d||{},this._super(b,c,h).done(function(){f(!0)}).fail(function(){f(!1)}),g.promise()},nodeSetStatus:function(b,c,d,e){if("ok"===c){var f=b.node,g=f.children?f.children[0]:null;g&&g.isStatusNode()&&a(g.tr).remove()}this._super(b,c,d,e)},treeClear:function(a){return this.nodeRemoveChildMarkup(this._makeHookContext(this.rootNode)),this._super(a)}})}(jQuery,window,document); + +/*! Extension 'jquery.fancytree.themeroller.min.js' */ +!function(a){"use strict";a.ui.fancytree.registerExtension({name:"themeroller",version:"0.0.1",options:{activeClass:"ui-state-active",foccusClass:"ui-state-focus",hoverClass:"ui-state-hover",selectedClass:"ui-state-highlight"},treeInit:function(b){this._super(b);var c=b.widget.element;"TABLE"===c[0].nodeName?(c.addClass("ui-widget ui-corner-all"),c.find(">thead tr").addClass("ui-widget-header"),c.find(">tbody").addClass("ui-widget-conent")):c.addClass("ui-widget ui-widget-content ui-corner-all"),c.delegate(".fancytree-node","mouseenter mouseleave",function(b){var c=a.ui.fancytree.getNode(b.target),d="mouseenter"===b.type;c.debug("hover: "+d),a(c.span).toggleClass("ui-state-hover ui-corner-all",d)})},treeDestroy:function(a){this._super(a),a.widget.element.removeClass("ui-widget ui-widget-content ui-corner-all")},nodeRenderStatus:function(b){var c=b.node,d=a(c.span);this._super(b),d.toggleClass("ui-state-active",c.isActive()),d.toggleClass("ui-state-focus",c.hasFocus()),d.toggleClass("ui-state-highlight",c.isSelected())}})}(jQuery,window,document); +})); diff --git a/filer/static/filer/js/popup_handling.js b/filer/static/filer/js/popup_handling.js index cf762081c..950edd134 100755 --- a/filer/static/filer/js/popup_handling.js +++ b/filer/static/filer/js/popup_handling.js @@ -1,25 +1,69 @@ -(function($) { - dismissPopupAndReload = function(win) { - document.location.reload(); - win.close(); - }; - dismissRelatedImageLookupPopup = function(win, chosenId, chosenThumbnailUrl, chosenDescriptionTxt) { - var name = windowname_to_id(win.name); - var img_name = name + '_thumbnail_img'; - var txt_name = name + '_description_txt'; - var clear_name = name + '_clear'; - var elem = document.getElementById(name); - document.getElementById(name).value = chosenId; - document.getElementById(img_name).src = chosenThumbnailUrl; - document.getElementById(txt_name).innerHTML = chosenDescriptionTxt; - document.getElementById(clear_name).style.display = 'inline'; - win.close(); - }; - dismissRelatedFolderLookupPopup = function(win, chosenId, chosenName) { - var id = windowname_to_id(win.name); - var id_name = id + '_description_txt'; - document.getElementById(id).value = chosenId; - document.getElementById(id_name).innerHTML = chosenName; - win.close(); - }; -})(jQuery); +(function($) { + dismissPopupAndReload = function(win) { + document.location.reload(); + win.close(); + }; + dismissRelatedImageLookupPopup = function(win, chosenId, chosenThumbnailUrl, chosenDescriptionTxt, file_url) { + var name = windowname_to_id(win.name); + var img_name = name + '_thumbnail_img'; + var txt_name = name + '_description_txt'; + var clear_name = name + '_clear'; + var link_name = name + '_link_to_file'; + var elem = document.getElementById(name); + document.getElementById(name).value = chosenId; + var img_element = document.getElementById(img_name); + var use_full_image = img_element.attributes["data-use-full-image"]; + if (!use_full_image || !file_url) { + img_element.src = chosenThumbnailUrl; + } else { + img_element.src = file_url; + } + img_element.classList.remove("no-filer-image") + var description = document.getElementById(txt_name); + if (description) { + description.innerHTML = chosenDescriptionTxt; + } + document.getElementById(clear_name).style.display = 'inline'; + var link = document.getElementById(link_name); + if (link && file_url) { + link.href = file_url; + } + win.close(); + }; + dismissRelatedFolderLookupPopup = function(win, chosenId, chosenName) { + var id = windowname_to_id(win.name); + var id_name = id + '_description_txt'; + document.getElementById(id).value = chosenId; + document.getElementById(id_name).innerHTML = chosenName; + document.getElementById(id + '_clear').style.display = 'inline'; + win.close(); + }; + showRelatedFilerObjectLookupPopup = function(triggerlink){ + if (typeof current_site !== 'undefined' && current_site == parseInt(current_site)){ + if (triggerlink.href.indexOf("current_site=") == -1){ + var new_link; + if (triggerlink.href.search(/\?/) >= 0) { + new_link = triggerlink.href + '¤t_site=' + current_site; + } else { + new_link = triggerlink.href + '?current_site=' + current_site; + } + triggerlink.href = new_link; + } + } + return _showRelatedObjectLookupPopup(triggerlink); + }; + _showRelatedObjectLookupPopup = function (triggeringLink) { + var name = triggeringLink.id.replace(/^lookup_/, ''); + name = id_to_windowname(name); + var href; + if (triggeringLink.href.search(/\?/) >= 0) { + href = triggeringLink.href + '&_popup=1'; + } else { + href = triggeringLink.href + '?_popup=1'; + } + var win = window.open(href, name, 'height=500,width=1120,resizable=yes,scrollbars=yes'); + win.focus(); + return false; + }; +})(jQuery); + diff --git a/filer/static/filer/js/raphael.js b/filer/static/filer/js/raphael.js deleted file mode 100644 index 8718b5bc7..000000000 --- a/filer/static/filer/js/raphael.js +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Raphael 1.3.1 - JavaScript Vector Library - * - * Copyright (c) 2008 - 2009 Dmitry Baranovskiy (http://raphaeljs.com) - * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. - */ -Raphael=(function(){var a=/[, ]+/,aO=/^(circle|rect|path|ellipse|text|image)$/,L=document,au=window,l={was:"Raphael" in au,is:au.Raphael},an=function(){if(an.is(arguments[0],"array")){var d=arguments[0],e=w[aW](an,d.splice(0,3+an.is(d[0],al))),S=e.set();for(var R=0,a0=d[m];R

      ";if(ag.childNodes[m]!=2){return null;}}an.svg=!(an.vml=an.type=="VML");aT[aY]=an[aY];an._id=0;an._oid=0;an.fn={};an.is=function(e,d){d=aZ.call(d);return((d=="object"||d=="undefined")&&typeof e==d)||(e==null&&d=="null")||aZ.call(aw.call(e).slice(8,-1))==d;};an.setWindow=function(d){au=d;L=au.document;};var aD=function(e){if(an.vml){var d=/^\s+|\s+$/g;aD=aj(function(R){var S;R=(R+at)[aP](d,at);try{var a0=new ActiveXObject("htmlfile");a0.write("");a0.close();S=a0.body;}catch(a2){S=createPopup().document.body;}var i=S.createTextRange();try{S.style.color=R;var a1=i.queryCommandValue("ForeColor");a1=((a1&255)<<16)|(a1&65280)|((a1&16711680)>>>16);return"#"+("000000"+a1[aA](16)).slice(-6);}catch(a2){return"none";}});}else{var E=L.createElement("i");E.title="Rapha\xebl Colour Picker";E.style.display="none";L.body[aL](E);aD=aj(function(i){E.style.color=i;return L.defaultView.getComputedStyle(E,at).getPropertyValue("color");});}return aD(e);};an.hsb2rgb=aj(function(a3,a1,a7){if(an.is(a3,"object")&&"h" in a3&&"s" in a3&&"b" in a3){a7=a3.b;a1=a3.s;a3=a3.h;}var R,S,a8;if(a7==0){return{r:0,g:0,b:0,hex:"#000"};}if(a3>1||a1>1||a7>1){a3/=255;a1/=255;a7/=255;}var a0=~~(a3*6),a4=(a3*6)-a0,E=a7*(1-a1),e=a7*(1-(a1*a4)),a9=a7*(1-(a1*(1-a4)));R=[a7,e,E,E,a9,a7,a7][a0];S=[a9,a7,a7,e,E,E,a9][a0];a8=[E,E,a9,a7,a7,e,E][a0];R*=255;S*=255;a8*=255;var a5={r:R,g:S,b:a8},d=(~~R)[aA](16),a2=(~~S)[aA](16),a6=(~~a8)[aA](16);d=d[aP](aU,"0");a2=a2[aP](aU,"0");a6=a6[aP](aU,"0");a5.hex="#"+d+a2+a6;return a5;},an);an.rgb2hsb=aj(function(d,e,a1){if(an.is(d,"object")&&"r" in d&&"g" in d&&"b" in d){a1=d.b;e=d.g;d=d.r;}if(an.is(d,"string")){var a3=an.getRGB(d);d=a3.r;e=a3.g;a1=a3.b;}if(d>1||e>1||a1>1){d/=255;e/=255;a1/=255;}var a0=g(d,e,a1),i=aI(d,e,a1),R,E,S=a0;if(i==a0){return{h:0,s:0,b:a0};}else{var a2=(a0-i);E=a2/a0;if(d==a0){R=(e-a1)/a2;}else{if(e==a0){R=2+((a1-d)/a2);}else{R=4+((d-e)/a2);}}R/=6;R<0&&R++;R>1&&R--;}return{h:R,s:E,b:S};},an);var aE=/,?([achlmqrstvxz]),?/gi;an._path2string=function(){return this.join(",")[aP](aE,"$1");};function aj(E,e,d){function i(){var R=Array[aY].slice.call(arguments,0),a0=R[az]("\u25ba"),S=i.cache=i.cache||{},a1=i.count=i.count||[];if(S[Q](a0)){return d?d(S[a0]):S[a0];}a1[m]>=1000&&delete S[a1.shift()];a1[f](a0);S[a0]=E[aW](e,R);return d?d(S[a0]):S[a0];}return i;}an.getRGB=aj(function(d){if(!d||!!((d=d+at).indexOf("-")+1)){return{r:-1,g:-1,b:-1,hex:"none",error:1};}if(d=="none"){return{r:-1,g:-1,b:-1,hex:"none"};}!(({hs:1,rg:1})[Q](d.substring(0,2))||d.charAt()=="#")&&(d=aD(d));var S,i,E,a2,a3,a0=d.match(x);if(a0){if(a0[2]){a2=G(a0[2].substring(5),16);E=G(a0[2].substring(3,5),16);i=G(a0[2].substring(1,3),16);}if(a0[3]){a2=G((a3=a0[3].charAt(3))+a3,16);E=G((a3=a0[3].charAt(2))+a3,16);i=G((a3=a0[3].charAt(1))+a3,16);}if(a0[4]){a0=a0[4][z](/\s*,\s*/);i=W(a0[0]);E=W(a0[1]);a2=W(a0[2]);}if(a0[5]){a0=a0[5][z](/\s*,\s*/);i=W(a0[0])*2.55;E=W(a0[1])*2.55;a2=W(a0[2])*2.55;}if(a0[6]){a0=a0[6][z](/\s*,\s*/);i=W(a0[0]);E=W(a0[1]);a2=W(a0[2]);return an.hsb2rgb(i,E,a2);}if(a0[7]){a0=a0[7][z](/\s*,\s*/);i=W(a0[0])*2.55;E=W(a0[1])*2.55;a2=W(a0[2])*2.55;return an.hsb2rgb(i,E,a2);}a0={r:i,g:E,b:a2};var e=(~~i)[aA](16),R=(~~E)[aA](16),a1=(~~a2)[aA](16);e=e[aP](aU,"0");R=R[aP](aU,"0");a1=a1[aP](aU,"0");a0.hex="#"+e+R+a1;return a0;}return{r:-1,g:-1,b:-1,hex:"none",error:1};},an);an.getColor=function(e){var i=this.getColor.start=this.getColor.start||{h:0,s:1,b:e||0.75},d=this.hsb2rgb(i.h,i.s,i.b);i.h+=0.075;if(i.h>1){i.h=0;i.s-=0.2;i.s<=0&&(this.getColor.start={h:0,s:1,b:i.b});}return d.hex;};an.getColor.reset=function(){delete this.start;};an.parsePathString=aj(function(d){if(!d){return null;}var i={a:7,c:6,h:1,l:2,m:2,q:4,s:4,t:2,v:1,z:0},e=[];if(an.is(d,"array")&&an.is(d[0],"array")){e=av(d);}if(!e[m]){(d+at)[aP](/([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig,function(R,E,a1){var a0=[],S=aZ.call(E);a1[aP](/(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig,function(a3,a2){a2&&a0[f](+a2);});while(a0[m]>=i[S]){e[f]([E][aS](a0.splice(0,i[S])));if(!i[S]){break;}}});}e[aA]=an._path2string;return e;});an.findDotsAtSegment=function(e,d,be,bc,a0,R,a2,a1,a8){var a6=1-a8,a5=aM(a6,3)*e+aM(a6,2)*3*a8*be+a6*3*a8*a8*a0+aM(a8,3)*a2,a3=aM(a6,3)*d+aM(a6,2)*3*a8*bc+a6*3*a8*a8*R+aM(a8,3)*a1,ba=e+2*a8*(be-e)+a8*a8*(a0-2*be+e),a9=d+2*a8*(bc-d)+a8*a8*(R-2*bc+d),bd=be+2*a8*(a0-be)+a8*a8*(a2-2*a0+be),bb=bc+2*a8*(R-bc)+a8*a8*(a1-2*R+bc),a7=(1-a8)*e+a8*be,a4=(1-a8)*d+a8*bc,E=(1-a8)*a0+a8*a2,i=(1-a8)*R+a8*a1,S=(90-ab.atan((ba-bd)/(a9-bb))*180/ab.PI);(ba>bd||a91){bi=ab.sqrt(by)*bi;bg=ab.sqrt(by)*bg;}var E=bi*bi,br=bg*bg,bt=(a4==S?-1:1)*ab.sqrt(ab.abs((E*br-E*bn*bn-br*bo*bo)/(E*bn*bn+br*bo*bo))),bd=bt*bi*bn/bg+(a9+a8)/2,bc=bt*-bg*bo/bi+(bE+bD)/2,a3=ab.asin(((bE-bc)/bg).toFixed(7)),a2=ab.asin(((bD-bc)/bg).toFixed(7));a3=a9a2){a3=a3-R*2;}if(!S&&a2>a3){a2=a2-R*2;}}else{a3=bb[0];a2=bb[1];bd=bb[2];bc=bb[3];}var a7=a2-a3;if(ab.abs(a7)>bf){var be=a2,bh=a8,a5=bD;a2=a3+bf*(S&&a2>a3?1:-1);a8=bd+bi*ab.cos(a2);bD=bc+bg*ab.sin(a2);bm=K(a8,bD,bi,bg,ba,0,S,bh,a5,[a2,be,bd,bc]);}a7=a2-a3;var a1=ab.cos(a3),bC=ab.sin(a3),a0=ab.cos(a2),bB=ab.sin(a2),bp=ab.tan(a7/4),bs=4/3*bi*bp,bq=4/3*bg*bp,bz=[a9,bE],bx=[a9+bs*bC,bE-bq*a1],bw=[a8+bs*bB,bD-bq*a0],bu=[a8,bD];bx[0]=2*bz[0]-bx[0];bx[1]=2*bz[1]-bx[1];if(bb){return[bx,bw,bu][aS](bm);}else{bm=[bx,bw,bu][aS](bm)[az]()[z](",");var bk=[];for(var bv=0,bl=bm[m];bv1000000000000&&(a0=0.5);ab.abs(S)>1000000000000&&(S=0.5);if(a0>0&&a0<1){e=M(i,d,R,E,a9,a8,a5,a2,a0);a6[f](e.x);a3[f](e.y);}if(S>0&&S<1){e=M(i,d,R,E,a9,a8,a5,a2,S);a6[f](e.x);a3[f](e.y);}a7=(a8-2*E+d)-(a2-2*a8+E);a4=2*(E-d)-2*(a8-E);a1=d-E;a0=(-a4+ab.sqrt(a4*a4-4*a7*a1))/2/a7;S=(-a4-ab.sqrt(a4*a4-4*a7*a1))/2/a7;ab.abs(a0)>1000000000000&&(a0=0.5);ab.abs(S)>1000000000000&&(S=0.5);if(a0>0&&a0<1){e=M(i,d,R,E,a9,a8,a5,a2,a0);a6[f](e.x);a3[f](e.y);}if(S>0&&S<1){e=M(i,d,R,E,a9,a8,a5,a2,S);a6[f](e.x);a3[f](e.y);}return{min:{x:aI[aW](0,a6),y:aI[aW](0,a3)},max:{x:g[aW](0,a6),y:g[aW](0,a3)}};}),H=aj(function(a9,a4){var R=r(a9),a5=a4&&r(a4),a6={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},d={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},a0=function(ba,bb){var i,bc;if(!ba){return["C",bb.x,bb.y,bb.x,bb.y,bb.x,bb.y];}!(ba[0] in {T:1,Q:1})&&(bb.qx=bb.qy=null);switch(ba[0]){case"M":bb.X=ba[1];bb.Y=ba[2];break;case"A":ba=["C"][aS](K[aW](0,[bb.x,bb.y][aS](ba.slice(1))));break;case"S":i=bb.x+(bb.x-(bb.bx||bb.x));bc=bb.y+(bb.y-(bb.by||bb.y));ba=["C",i,bc][aS](ba.slice(1));break;case"T":bb.qx=bb.x+(bb.x-(bb.qx||bb.x));bb.qy=bb.y+(bb.y-(bb.qy||bb.y));ba=["C"][aS](aK(bb.x,bb.y,bb.qx,bb.qy,ba[1],ba[2]));break;case"Q":bb.qx=ba[1];bb.qy=ba[2];ba=["C"][aS](aK(bb.x,bb.y,ba[1],ba[2],ba[3],ba[4]));break;case"L":ba=["C"][aS](aX(bb.x,bb.y,ba[1],ba[2]));break;case"H":ba=["C"][aS](aX(bb.x,bb.y,ba[1],bb.y));break;case"V":ba=["C"][aS](aX(bb.x,bb.y,bb.x,ba[1]));break;case"Z":ba=["C"][aS](aX(bb.x,bb.y,bb.X,bb.Y));break;}return ba;},e=function(ba,bb){if(ba[bb][m]>7){ba[bb].shift();var bc=ba[bb];while(bc[m]){ba.splice(bb++,0,["C"][aS](bc.splice(0,6)));}ba.splice(bb,1);a7=g(R[m],a5&&a5[m]||0);}},E=function(be,bd,bb,ba,bc){if(be&&bd&&be[bc][0]=="M"&&bd[bc][0]!="M"){bd.splice(bc,0,["M",ba.x,ba.y]);bb.bx=0;bb.by=0;bb.x=be[bc][1];bb.y=be[bc][2];a7=g(R[m],a5&&a5[m]||0);}};for(var a2=0,a7=g(R[m],a5&&a5[m]||0);a23){return{container:1,x:arguments[0],y:arguments[1],width:arguments[2],height:arguments[3]};}}},aG=function(d,i){var e=this;for(var E in i){if(i[Q](E)&&!(E in d)){switch(typeof i[E]){case"function":(function(R){d[E]=d===e?R:function(){return R[aW](e,arguments);};})(i[E]);break;case"object":d[E]=d[E]||{};aG.call(this,d[E],i[E]);break;default:d[E]=i[E];break;}}}},ak=function(d,e){d==e.top&&(e.top=d.prev);d==e.bottom&&(e.bottom=d.next);d.next&&(d.next.prev=d.prev);d.prev&&(d.prev.next=d.next);},Y=function(d,e){if(e.top===d){return;}ak(d,e);d.next=null;d.prev=e.top;e.top.next=d;e.top=d;},k=function(d,e){if(e.bottom===d){return;}ak(d,e);d.next=e.bottom;d.prev=null;e.bottom.prev=d;e.bottom=d;},A=function(e,d,i){ak(e,i);d==i.top&&(i.top=e);d.next&&(d.next.prev=e);e.next=d.next;e.prev=d;d.next=e;},aq=function(e,d,i){ak(e,i);d==i.bottom&&(i.bottom=e);d.prev&&(d.prev.next=e);e.prev=d.prev;d.prev=e;e.next=d;},s=function(d){return function(){throw new Error("Rapha\xebl: you are calling to method \u201c"+d+"\u201d of removed object");};},ar=/^r(?:\(([^,]+?)\s*,\s*([^\)]+?)\))?/;if(an.svg){aT[aY].svgns="http://www.w3.org/2000/svg";aT[aY].xlink="http://www.w3.org/1999/xlink";var O=function(d){return +d+(~~d===d)*0.5;},V=function(S){for(var e=0,E=S[m];e0.5)*2-1);aM(a1-0.5,2)+aM(S-0.5,2)>0.25&&(S=ab.sqrt(0.25-aM(a1-0.5,2))*ba+0.5)&&S!=0.5&&(S=S.toFixed(5)-0.00001*ba);}return at;});a7=a7[z](/\s*\-\s*/);if(a4=="linear"){var a0=a7.shift();a0=-W(a0);if(isNaN(a0)){return null;}var R=[0,0,ab.cos(a0*ab.PI/180),ab.sin(a0*ab.PI/180)],a6=1/(g(ab.abs(R[2]),ab.abs(R[3]))||1);R[2]*=a6;R[3]*=a6;if(R[2]<0){R[0]=-R[2];R[2]=0;}if(R[3]<0){R[1]=-R[3];R[3]=0;}}var a3=p(a7);if(!a3){return null;}var e=aJ(a4+"Gradient");e.id="r"+(an._id++)[aA](36);aJ(e,a4=="radial"?{fx:a1,fy:S}:{x1:R[0],y1:R[1],x2:R[2],y2:R[3]});d.defs[aL](e);for(var a2=0,a8=a3[m];a2a1.height)&&(a1.height=a0.y+a0.height-a1.y);(a0.x+a0.width-a1.x>a1.width)&&(a1.width=a0.x+a0.width-a1.x);}}E&&this.hide();return a1;};ax[aY].attr=function(){if(this.removed){return this;}if(arguments[m]==0){var R={};for(var E in this.attrs){if(this.attrs[Q](E)){R[E]=this.attrs[E];}}this._.rt.deg&&(R.rotation=this.rotate());(this._.sx!=1||this._.sy!=1)&&(R.scale=this.scale());R.gradient&&R.fill=="none"&&(R.fill=R.gradient)&&delete R.gradient;return R;}if(arguments[m]==1&&an.is(arguments[0],"string")){if(arguments[0]=="translation"){return t.call(this);}if(arguments[0]=="rotation"){return this.rotate();}if(arguments[0]=="scale"){return this.scale();}if(arguments[0]=="fill"&&this.attrs.fill=="none"&&this.attrs.gradient){return this.attrs.gradient;}return this.attrs[arguments[0]];}if(arguments[m]==1&&an.is(arguments[0],"array")){var d={};for(var e in arguments[0]){if(arguments[0][Q](e)){d[arguments[0][e]]=this.attrs[arguments[0][e]];}}return d;}if(arguments[m]==2){var S={};S[arguments[0]]=arguments[1];aa(this,S);}else{if(arguments[m]==1&&an.is(arguments[0],"object")){aa(this,arguments[0]);}}return this;};ax[aY].toFront=function(){if(this.removed){return this;}this.node.parentNode[aL](this.node);var d=this.paper;d.top!=this&&Y(this,d);return this;};ax[aY].toBack=function(){if(this.removed){return this;}if(this.node.parentNode.firstChild!=this.node){this.node.parentNode.insertBefore(this.node,this.node.parentNode.firstChild);k(this,this.paper);var d=this.paper;}return this;};ax[aY].insertAfter=function(d){if(this.removed){return this;}var e=d.node;if(e.nextSibling){e.parentNode.insertBefore(this.node,e.nextSibling);}else{e.parentNode[aL](this.node);}A(this,d,this.paper);return this;};ax[aY].insertBefore=function(d){if(this.removed){return this;}var e=d.node;e.parentNode.insertBefore(this.node,e);aq(this,d,this.paper);return this;};var P=function(e,d,S,R){d=O(d);S=O(S);var E=aJ("circle");e.canvas&&e.canvas[aL](E);var i=new ax(E,e);i.attrs={cx:d,cy:S,r:R,fill:"none",stroke:"#000"};i.type="circle";aJ(E,i.attrs);return i;};var aF=function(i,d,a1,e,S,a0){d=O(d);a1=O(a1);var R=aJ("rect");i.canvas&&i.canvas[aL](R);var E=new ax(R,i);E.attrs={x:d,y:a1,width:e,height:S,r:a0||0,rx:a0||0,ry:a0||0,fill:"none",stroke:"#000"};E.type="rect";aJ(R,E.attrs);return E;};var ai=function(e,d,a0,S,R){d=O(d);a0=O(a0);var E=aJ("ellipse");e.canvas&&e.canvas[aL](E);var i=new ax(E,e);i.attrs={cx:d,cy:a0,rx:S,ry:R,fill:"none",stroke:"#000"};i.type="ellipse";aJ(E,i.attrs);return i;};var o=function(i,a0,d,a1,e,S){var R=aJ("image");aJ(R,{x:d,y:a1,width:e,height:S,preserveAspectRatio:"none"});R.setAttributeNS(i.xlink,"href",a0);i.canvas&&i.canvas[aL](R);var E=new ax(R,i);E.attrs={x:d,y:a1,width:e,height:S,src:a0};E.type="image";return E;};var X=function(e,d,S,R){var E=aJ("text");aJ(E,{x:d,y:S,"text-anchor":"middle"});e.canvas&&e.canvas[aL](E);var i=new ax(E,e);i.attrs={x:d,y:S,"text-anchor":"middle",text:R,font:j.font,stroke:"none",fill:"#000"};i.type="text";aa(i,i.attrs);return i;};var aV=function(e,d){this.width=e||this.width;this.height=d||this.height;this.canvas[v]("width",this.width);this.canvas[v]("height",this.height);return this;};var w=function(){var E=ao[aW](null,arguments),i=E&&E.container,e=E.x,a0=E.y,R=E.width,d=E.height;if(!i){throw new Error("SVG container not found.");}var S=aJ("svg");R=R||512;d=d||342;aJ(S,{xmlns:"http://www.w3.org/2000/svg",version:1.1,width:R,height:d});if(i==1){S.style.cssText="position:absolute;left:"+e+"px;top:"+a0+"px";L.body[aL](S);}else{if(i.firstChild){i.insertBefore(S,i.firstChild);}else{i[aL](S);}}i=new aT;i.width=R;i.height=d;i.canvas=S;aG.call(i,i,an.fn);i.clear();return i;};aT[aY].clear=function(){var d=this.canvas;while(d.firstChild){d.removeChild(d.firstChild);}this.bottom=this.top=null;(this.desc=aJ("desc"))[aL](L.createTextNode("Created with Rapha\xebl"));d[aL](this.desc);d[aL](this.defs=aJ("defs"));};aT[aY].remove=function(){this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas);for(var d in this){this[d]=s(d);}};}if(an.vml){var aH=function(a8){var a5=/[ahqstv]/ig,a0=r;(a8+at).match(a5)&&(a0=H);a5=/[clmz]/g;if(a0==r&&!(a8+at).match(a5)){var e={M:"m",L:"l",C:"c",Z:"x",m:"t",l:"r",c:"v",z:"x"},R=/([clmz]),?([^clmz]*)/gi,S=/-?[^,\s-]+/g;var a4=(a8+at)[aP](R,function(a9,bb,i){var ba=[];i[aP](S,function(bc){ba[f](O(bc));});return e[bb]+ba;});return a4;}var a6=a0(a8),E,a4=[],d;for(var a2=0,a7=a6[m];a21&&(e=1);a7.opacity=e;}a8.fill&&(a7.on=true);if(a7.on==null||a8.fill=="none"){a7.on=false;}if(a7.on&&a8.fill){var i=a8.fill.match(c);if(i){a7.src=i[1];a7.type="tile";}else{a7.color=an.getRGB(a8.fill).hex;a7.src=at;a7.type="solid";if(an.getRGB(a8.fill).error&&(bd.type in {circle:1,ellipse:1}||(a8.fill+at).charAt()!="r")&&b(bd,a8.fill)){a9.fill="none";a9.gradient=a8.fill;}}}ba&&a6[aL](a7);var R=(a6.getElementsByTagName("stroke")&&a6.getElementsByTagName("stroke")[0]),bb=false;!R&&(bb=R=ah("stroke"));if((a8.stroke&&a8.stroke!="none")||a8["stroke-width"]||a8["stroke-opacity"]!=null||a8["stroke-dasharray"]||a8["stroke-miterlimit"]||a8["stroke-linejoin"]||a8["stroke-linecap"]){R.on=true;}(a8.stroke=="none"||R.on==null||a8.stroke==0||a8["stroke-width"]==0)&&(R.on=false);R.on&&a8.stroke&&(R.color=an.getRGB(a8.stroke).hex);var e=((+a9["stroke-opacity"]+1||2)-1)*((+a9.opacity+1||2)-1),a4=(W(a8["stroke-width"])||1)*0.75;e<0&&(e=0);e>1&&(e=1);a8["stroke-width"]==null&&(a4=a9["stroke-width"]);a8["stroke-width"]&&(R.weight=a4);a4&&a4<1&&(e*=a4)&&(R.weight=1);R.opacity=e;a8["stroke-linejoin"]&&(R.joinstyle=a8["stroke-linejoin"]||"miter");R.miterlimit=a8["stroke-miterlimit"]||8;a8["stroke-linecap"]&&(R.endcap=a8["stroke-linecap"]=="butt"?"flat":a8["stroke-linecap"]=="square"?"square":"round");if(a8["stroke-dasharray"]){var a5={"-":"shortdash",".":"shortdot","-.":"shortdashdot","-..":"shortdashdotdot",". ":"dot","- ":"dash","--":"longdash","- .":"dashdot","--.":"longdashdot","--..":"longdashdotdot"};R.dashstyle=a5[Q](a8["stroke-dasharray"])?a5[a8["stroke-dasharray"]]:at;}bb&&a6[aL](R);}if(bd.type=="text"){var a0=bd.paper.span.style;a9.font&&(a0.font=a9.font);a9["font-family"]&&(a0.fontFamily=a9["font-family"]);a9["font-size"]&&(a0.fontSize=a9["font-size"]);a9["font-weight"]&&(a0.fontWeight=a9["font-weight"]);a9["font-style"]&&(a0.fontStyle=a9["font-style"]);bd.node.string&&(bd.paper.span.innerHTML=(bd.node.string+at)[aP](/"));bd.W=a9.w=bd.paper.span.offsetWidth;bd.H=a9.h=bd.paper.span.offsetHeight;bd.X=a9.x;bd.Y=a9.y+O(bd.H/2);switch(a9["text-anchor"]){case"start":bd.node.style["v-text-align"]="left";bd.bbx=O(bd.W/2);break;case"end":bd.node.style["v-text-align"]="right";bd.bbx=-O(bd.W/2);break;default:bd.node.style["v-text-align"]="center";break;}}};var b=function(d,a1){d.attrs=d.attrs||{};var a2=d.attrs,a4=d.node.getElementsByTagName("fill"),S="linear",a0=".5 .5";d.attrs.gradient=a1;a1=(a1+at)[aP](ar,function(a6,a7,i){S="radial";if(a7&&i){a7=W(a7);i=W(i);aM(a7-0.5,2)+aM(i-0.5,2)>0.25&&(i=ab.sqrt(0.25-aM(a7-0.5,2))*((i>0.5)*2-1)+0.5);a0=a7+am+i;}return at;});a1=a1[z](/\s*\-\s*/);if(S=="linear"){var e=a1.shift();e=-W(e);if(isNaN(e)){return null;}}var R=p(a1);if(!R){return null;}d=d.shape||d.node;a4=a4[0]||ah("fill");if(R[m]){a4.on=true;a4.method="none";a4.type=(S=="radial")?"gradientradial":"gradient";a4.color=R[0].color;a4.color2=R[R[m]-1].color;var a5=[];for(var E=0,a3=R[m];E');};}catch(af){ah=function(d){return L.createElement("<"+d+' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');};}var w=function(){var i=ao[aW](null,arguments),d=i.container,a2=i.height,a3,e=i.width,a1=i.x,a0=i.y;if(!d){throw new Error("VML container not found.");}var R=new aT,S=R.canvas=L.createElement("div"),E=S.style;e=e||512;a2=a2||342;e==+e&&(e+="px");a2==+a2&&(a2+="px");R.width=1000;R.height=1000;R.coordsize="1000 1000";R.coordorigin="0 0";R.span=L.createElement("span");R.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";S[aL](R.span);E.cssText=an.format("width:{0};height:{1};position:absolute;clip:rect(0 {0} {1} 0);overflow:hidden",e,a2);if(d==1){L.body[aL](S);E.left=a1+"px";E.top=a0+"px";}else{d.style.width=e;d.style.height=a2;if(d.firstChild){d.insertBefore(S,d.firstChild);}else{d[aL](S);}}aG.call(R,R,an.fn);return R;};aT[aY].clear=function(){this.canvas.innerHTML=at;this.span=L.createElement("span");this.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";this.canvas[aL](this.span);this.bottom=this.top=null;};aT[aY].remove=function(){this.canvas.parentNode.removeChild(this.canvas);for(var d in this){this[d]=s(d);}};}if((/^Apple|^Google/).test(navigator.vendor)&&!(navigator.userAgent.indexOf("Version/4.0")+1)){aT[aY].safari=function(){var d=this.rect(-99,-99,this.width+99,this.height+99);setTimeout(function(){d.remove();});};}else{aT[aY].safari=function(){};}var ae=(function(){if(L.addEventListener){return function(R,i,e,d){var E=function(S){return e.call(d,S);};R.addEventListener(i,E,false);return function(){R.removeEventListener(i,E,false);return true;};};}else{if(L.attachEvent){return function(S,E,i,e){var R=function(a0){return i.call(e,a0||au.event);};S.attachEvent("on"+E,R);var d=function(){S.detachEvent("on"+E,R);return true;};return d;};}}})();for(var ac=F[m];ac--;){(function(d){ax[aY][d]=function(e){if(an.is(e,"function")){this.events=this.events||[];this.events.push({name:d,f:e,unbind:ae(this.shape||this.node,d,e,this)});}return this;};ax[aY]["un"+d]=function(E){var i=this.events,e=i[m];while(e--){if(i[e].name==d&&i[e].f==E){i[e].unbind();i.splice(e,1);!i.length&&delete this.events;return this;}}return this;};})(F[ac]);}ax[aY].hover=function(e,d){return this.mouseover(e).mouseout(d);};ax[aY].unhover=function(e,d){return this.unmouseover(e).unmouseout(d);};aT[aY].circle=function(d,i,e){return P(this,d||0,i||0,e||0);};aT[aY].rect=function(d,R,e,i,E){return aF(this,d||0,R||0,e||0,i||0,E||0);};aT[aY].ellipse=function(d,E,i,e){return ai(this,d||0,E||0,i||0,e||0);};aT[aY].path=function(d){d&&!an.is(d,"string")&&!an.is(d[0],"array")&&(d+=at);return q(an.format[aW](an,arguments),this);};aT[aY].image=function(E,d,R,e,i){return o(this,E||"about:blank",d||0,R||0,e||0,i||0);};aT[aY].text=function(d,i,e){return X(this,d||0,i||0,e||at);};aT[aY].set=function(d){arguments[m]>1&&(d=Array[aY].splice.call(arguments,0,arguments[m]));return new T(d);};aT[aY].setSize=aV;aT[aY].top=aT[aY].bottom=null;aT[aY].raphael=an;function u(){return this.x+am+this.y;}ax[aY].scale=function(a6,a5,E,e){if(a6==null&&a5==null){return{x:this._.sx,y:this._.sy,toString:u};}a5=a5||a6;!+a5&&(a5=a6);var ba,a8,a9,a7,bm=this.attrs;if(a6!=0){var a4=this.getBBox(),a1=a4.x+a4.width/2,R=a4.y+a4.height/2,bl=a6/this._.sx,bk=a5/this._.sy;E=(+E||E==0)?E:a1;e=(+e||e==0)?e:R;var a3=~~(a6/ab.abs(a6)),a0=~~(a5/ab.abs(a5)),be=this.node.style,bo=E+(a1-E)*bl,bn=e+(R-e)*bk;switch(this.type){case"rect":case"image":var a2=bm.width*a3*bl,bd=bm.height*a0*bk;this.attr({height:bd,r:bm.r*aI(a3*bl,a0*bk),width:a2,x:bo-a2/2,y:bn-bd/2});break;case"circle":case"ellipse":this.attr({rx:bm.rx*a3*bl,ry:bm.ry*a0*bk,r:bm.r*aI(a3*bl,a0*bk),cx:bo,cy:bn});break;case"path":var bg=ad(bm.path),bh=true;for(var bj=0,bc=bg[m];bjS){if(e&&!a8.start){a6=an.findDotsAtSegment(a5,a4,E[1],E[2],E[3],E[4],E[5],E[6],(S-a3)/a1);R+=["C",a6.start.x,a6.start.y,a6.m.x,a6.m.y,a6.x,a6.y];if(a0){return R;}a8.start=R;R=["M",a6.x,a6.y+"C",a6.n.x,a6.n.y,a6.end.x,a6.end.y,E[5],E[6]][az]();a3+=a1;a5=+E[5];a4=+E[6];continue;}if(!d&&!e){a6=an.findDotsAtSegment(a5,a4,E[1],E[2],E[3],E[4],E[5],E[6],(S-a3)/a1);return{x:a6.x,y:a6.y,alpha:a6.alpha};}}a3+=a1;a5=+E[5];a4=+E[6];}R+=E;}a8.end=R;a6=d?a3:e?a8:an.findDotsAtSegment(a5,a4,E[1],E[2],E[3],E[4],E[5],E[6],1);a6.alpha&&(a6={x:a6.x,y:a6.y,alpha:a6.alpha});return a6;};},n=aj(function(E,d,a0,S,a6,a5,a4,a3){var R={x:0,y:0},a2=0;for(var a1=0;a1<1.01;a1+=0.01){var e=M(E,d,a0,S,a6,a5,a4,a3,a1);a1&&(a2+=ab.sqrt(aM(R.x-e.x,2)+aM(R.y-e.y,2)));R=e;}return a2;});var ap=aB(1),C=aB(),J=aB(0,1);ax[aY].getTotalLength=function(){if(this.type!="path"){return;}return ap(this.attrs.path);};ax[aY].getPointAtLength=function(d){if(this.type!="path"){return;}return C(this.attrs.path,d);};ax[aY].getSubpath=function(i,e){if(this.type!="path"){return;}if(ab.abs(this.getTotalLength()-e)<0.000001){return J(this.attrs.path,i).end;}var d=J(this.attrs.path,e,1);return i?J(d,i).end:d;};an.easing_formulas={linear:function(d){return d;},"<":function(d){return aM(d,3);},">":function(d){return aM(d-1,3)+1;},"<>":function(d){d=d*2;if(d<1){return aM(d,3)/2;}d-=2;return(aM(d,3)+2)/2;},backIn:function(e){var d=1.70158;return e*e*((d+1)*e-d);},backOut:function(e){e=e-1;var d=1.70158;return e*e*((d+1)*e+d)+1;},elastic:function(i){if(i==0||i==1){return i;}var e=0.3,d=e/4;return aM(2,-10*i)*ab.sin((i-d)*(2*ab.PI)/e)+1;},bounce:function(E){var e=7.5625,i=2.75,d;if(E<(1/i)){d=e*E*E;}else{if(E<(2/i)){E-=(1.5/i);d=e*E*E+0.75;}else{if(E<(2.5/i)){E-=(2.25/i);d=e*E*E+0.9375;}else{E-=(2.625/i);d=e*E*E+0.984375;}}}return d;}};var I={length:0},aR=function(){var a2=+new Date;for(var be in I){if(be!="length"&&I[Q](be)){var bj=I[be];if(bj.stop){delete I[be];I[m]--;continue;}var a0=a2-bj.start,bb=bj.ms,ba=bj.easing,bf=bj.from,a7=bj.diff,E=bj.to,a6=bj.t,a9=bj.prev||0,a1=bj.el,R=bj.callback,a8={},d;if(a0255?255:(d<0?0:d);},t=function(d,i){if(d==null){return{x:this._.tx,y:this._.ty,toString:u};}this._.tx+=+d;this._.ty+=+i;switch(this.type){case"circle":case"ellipse":this.attr({cx:+d+this.attrs.cx,cy:+i+this.attrs.cy});break;case"rect":case"image":case"text":this.attr({x:+d+this.attrs.x,y:+i+this.attrs.y});break;case"path":var e=ad(this.attrs.path);e[0][1]+=+d;e[0][2]+=+i;this.attr({path:e});break;}return this;};ax[aY].animateWith=function(e,i,d,R,E){I[e.id]&&(i.start=I[e.id].start);return this.animate(i,d,R,E);};ax[aY].animateAlong=ay();ax[aY].animateAlongBack=ay(1);function ay(d){return function(E,i,e,S){var R={back:d};an.is(e,"function")?(S=e):(R.rot=e);E&&E.constructor==ax&&(E=E.attrs.path);E&&(R.along=E);return this.animate(R,i,S);};}ax[aY].onAnimation=function(d){this._run=d||0;return this;};ax[aY].animate=function(be,a5,a4,E){if(an.is(a4,"function")||!a4){E=a4||null;}var a9={},e={},a2={};for(var a6 in be){if(be[Q](a6)){if(Z[Q](a6)){a9[a6]=this.attr(a6);(a9[a6]==null)&&(a9[a6]=j[a6]);e[a6]=be[a6];switch(Z[a6]){case"along":var bc=ap(be[a6]),a7=C(be[a6],bc*!!be.back),R=this.getBBox();a2[a6]=bc/a5;a2.tx=R.x;a2.ty=R.y;a2.sx=a7.x;a2.sy=a7.y;e.rot=be.rot;e.back=be.back;e.len=bc;be.rot&&(a2.r=W(this.rotate())||0);break;case"number":a2[a6]=(e[a6]-a9[a6])/a5;break;case"colour":a9[a6]=an.getRGB(a9[a6]);var a8=an.getRGB(e[a6]);a2[a6]={r:(a8.r-a9[a6].r)/a5,g:(a8.g-a9[a6].g)/a5,b:(a8.b-a9[a6].b)/a5};break;case"path":var S=H(a9[a6],e[a6]);a9[a6]=S[0];var a3=S[1];a2[a6]=[];for(var bb=0,a1=a9[a6][m];bb=200&&n.status<=399?(t.confirmed_paths.push(r.at_2x_path),e(!0)):e(!1)},n.send()},e.RetinaImage=n,n.prototype.swap=function(e){function n(){t.el.complete?(t.el.setAttribute("width",t.el.offsetWidth),t.el.setAttribute("height",t.el.offsetHeight),t.el.setAttribute("src",e)):setTimeout(n,5)}typeof e=="undefined"&&(e=this.path.at_2x_path);var t=this;n()},e.devicePixelRatio>1&&(window.onload=function(){var e=document.getElementsByTagName("img"),t=[],r,i;for(r=0;r { + // Find all file widgets and clean up "add new" buttons + const cleanupAddButtons = () => { + document.querySelectorAll('.filer-widget').forEach((widget) => { + const hiddenInput = widget.querySelector('input[type="text"][id]'); + if (hiddenInput) { + const widgetId = hiddenInput.id; + const addButton = document.querySelector(`#add_${widgetId}`); + if (addButton) { + addButton.remove(); + } + } + }); + }; + + cleanupAddButtons(); + + // Also handle dynamically added widgets (e.g., in inline formsets) + const observer = new MutationObserver(() => { + cleanupAddButtons(); + }); + + observer.observe(document.body, { + childList: true, + subtree: true + }); +}); diff --git a/filer/static/filer/js/widgets/admin-folder-widget.js b/filer/static/filer/js/widgets/admin-folder-widget.js new file mode 100644 index 000000000..14c5d2206 --- /dev/null +++ b/filer/static/filer/js/widgets/admin-folder-widget.js @@ -0,0 +1,64 @@ +// Admin Folder Widget JavaScript +'use strict'; + +document.addEventListener('DOMContentLoaded', () => { + const initFolderWidget = (widget) => { + const clearButton = widget.querySelector('.filerClearer'); + const input = widget.querySelector('input[type="text"]'); + const folderName = widget.querySelector('.description_text'); + const thumbnailImg = widget.querySelector('.thumbnail_img'); + const addFolderButton = widget.querySelector('.related-lookup'); + + if (!clearButton || !input) { + return; + } + + // Avoid duplicate initialization + if (clearButton.dataset.initialized) { + return; + } + clearButton.dataset.initialized = 'true'; + + clearButton.addEventListener('click', (e) => { + e.preventDefault(); + + if (folderName) { + folderName.textContent = ''; + } + if (input) { + input.removeAttribute('value'); + input.value = ''; + } + if (thumbnailImg) { + thumbnailImg.classList.add('hidden'); + } + clearButton.classList.add('hidden'); + if (addFolderButton) { + addFolderButton.classList.remove('hidden'); + } + }); + }; + + // Initialize all folder widgets + document.querySelectorAll('.filer-dropzone-folder').forEach(initFolderWidget); + + // Handle dynamically added widgets (e.g., in inline formsets) + const observer = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + mutation.addedNodes.forEach((node) => { + if (node.nodeType === 1) { // Element node + if (node.classList?.contains('filer-dropzone-folder')) { + initFolderWidget(node); + } + // Also check child nodes + node.querySelectorAll?.('.filer-dropzone-folder').forEach(initFolderWidget); + } + }); + }); + }); + + observer.observe(document.body, { + childList: true, + subtree: true + }); +}); diff --git a/filer/storage.py b/filer/storage.py index dfb4e6bcb..63e5513d2 100755 --- a/filer/storage.py +++ b/filer/storage.py @@ -1,5 +1,25 @@ #-*- coding: utf-8 -*- +import logging +import urllib.parse + from django.core.files.storage import FileSystemStorage +from django.utils.encoding import smart_str + +try: + from botocore.exceptions import ClientError as BotoClientError +except ImportError: + BotoClientError = Exception + +try: + from storages.backends.s3boto import S3BotoStorage +except ImportError: + try: + from storages.backends.s3boto3 import S3Boto3Storage as S3BotoStorage + except ImportError: + S3BotoStorage = None + + +logger = logging.getLogger(__name__) class PublicFileSystemStorage(FileSystemStorage): @@ -19,3 +39,55 @@ class PrivateFileSystemStorage(FileSystemStorage): See ``filer.settings`` for the defaults for ``location`` and ``base_url``. """ is_secure = True + + +def filepath_to_url(path): + if path is None: + return path + return urllib.parse.quote(smart_str(path).replace("\\", "/"), safe="/~!*()") + + +if S3BotoStorage is not None: + class PatchedS3BotoStorage(S3BotoStorage): + + def url(self, name): + if self.custom_domain: + name = filepath_to_url(self._normalize_name(self._clean_name(name))) + return "%s://%s/%s" % ('https' if self.secure_urls else 'http', + self.custom_domain, name) + return self.connection.generate_url( + self.querystring_expire, + method='GET', bucket=self.bucket.name, key=self._encode_name(name), + query_auth=self.querystring_auth, force_http=not self.secure_urls) + + def has_public_read(self, object_key): + old_acl = object_key.Acl().grants + if not old_acl: + return False + for right in old_acl: + if ( + 'AllUsers' in right.get('Grantee', {}).get('URI', '') and + right.get('Permission', '').upper() == 'READ' + ): + return True + return False + + def copy(self, src_name, dst_name): + src_path = self._normalize_name(self._clean_name(src_name)) + dst_path = self._normalize_name(self._clean_name(dst_name)) + copy_source = { + 'Bucket': self.bucket.name, + 'Key': src_path + } + source_obj = self.bucket.Object(src_path) + try: + extra_args = { + 'ContentType': source_obj.content_type + } + except BotoClientError as error: + logger.warning("Copy: source error: %s", error) + return False + # we cannot preserve acl in boto3, but we can give public read + if self.has_public_read(source_obj): + extra_args['ACL'] = 'public-read' + self.bucket.copy(copy_source, dst_path, extra_args) diff --git a/filer/tasks.py b/filer/tasks.py new file mode 100644 index 000000000..d060d2b58 --- /dev/null +++ b/filer/tasks.py @@ -0,0 +1,8 @@ +from celery import shared_task + +from django.core.management import call_command + + +@shared_task +def take_out_filer_trash_task(): + call_command("take_out_filer_trash") diff --git a/filer/templates/admin/filer/actions.html b/filer/templates/admin/filer/actions.html index dfb09bf77..a0b01fbd7 100644 --- a/filer/templates/admin/filer/actions.html +++ b/filer/templates/admin/filer/actions.html @@ -1,16 +1,19 @@ {% load i18n %} -
      + + diff --git a/filer/templates/admin/filer/base_site.html b/filer/templates/admin/filer/base_site.html index b3f63fd2f..2a66e751d 100644 --- a/filer/templates/admin/filer/base_site.html +++ b/filer/templates/admin/filer/base_site.html @@ -1,6 +1,17 @@ {% extends "admin/base_site.html" %} -{% load i18n filermedia %} +{% load i18n static filer_admin_tags %} -{% block extrastyle %}{{ block.super }} - +{% block extrastyle %} + {{ block.super }} + + {% icon_css_library %} +{% endblock %} + +{% block extrahead %} + {{ block.super }} + + {# upload stuff #} + {{ media.js }} + + {% endblock %} diff --git a/filer/templates/admin/filer/breadcrumbs.html b/filer/templates/admin/filer/breadcrumbs.html index aba5fec45..a8dceac9d 100644 --- a/filer/templates/admin/filer/breadcrumbs.html +++ b/filer/templates/admin/filer/breadcrumbs.html @@ -1,16 +1,24 @@ -{% load i18n %} -{% load url from future %} +{% load i18n filer_admin_tags %} + diff --git a/filer/templates/admin/filer/change_form.html b/filer/templates/admin/filer/change_form.html index 2d208f1a5..34aeb85b7 100644 --- a/filer/templates/admin/filer/change_form.html +++ b/filer/templates/admin/filer/change_form.html @@ -1,36 +1,36 @@ {% extends "admin/change_form.html" %} -{% load i18n admin_modify adminmedia filermedia %} - -{% block extrahead %}{{ block.super }} -{% endblock %} +{% load i18n admin_modify static filer_admin_tags %} {% block breadcrumbs %} -{% with original as instance %} -{% include "admin/filer/breadcrumbs.html" %} -{% endwith %} + {% with original as instance %} + {% include "admin/filer/breadcrumbs.html" %} + {% endwith %} {% endblock %} -{% block extrastyle %}{{ block.super }} - +{% block extrastyle %} + {{ block.super }} + + {% icon_css_library %} {% endblock %} -{% block coltype %}colMS{% endblock %} {% block after_field_sets %} - {% if is_popup and select_folder %}{% endif %} + {% filer_admin_context_hidden_formfields %} {% endblock %} {% block sidebar %} - + {% block file_sidebar %} + {% with original.duplicates as duplicates %} + {% if duplicates %} +
      +

      {% translate "Duplicates" %}

      + +
      + {% endif %} + {% endwith %} + {% endblock %} {% endblock %} diff --git a/filer/templates/admin/filer/change_list.html b/filer/templates/admin/filer/change_list.html new file mode 100644 index 000000000..e8f314ab0 --- /dev/null +++ b/filer/templates/admin/filer/change_list.html @@ -0,0 +1,16 @@ +{% extends "admin/change_list.html" %} + +{% block extrastyle %} +{{block.super}} + {% comment %} + Because there are no general action in the changelist, the css for actions + drop-down must be adjusted. + {% endcomment %} + +{% endblock %} + + diff --git a/filer/templates/admin/filer/delete_confirmation.html b/filer/templates/admin/filer/delete_confirmation.html index e5e0efb67..635fbfb05 100644 --- a/filer/templates/admin/filer/delete_confirmation.html +++ b/filer/templates/admin/filer/delete_confirmation.html @@ -1,38 +1,10 @@ -{% extends "admin/filer/base_site.html" %} -{% load i18n %} -{% load url from future %} -{% load admin_urls %} +{% extends "admin/delete_confirmation.html" %} +{% load i18n static %} -{% block breadcrumbs %} -{% include "admin/filer/breadcrumbs.html" with instance=object breadcrumbs_action="Delete" %} +{% block extrastyle %}{{ block.super }} + {% endblock %} -{% block content %} -{% if perms_lacking or protected %} - {% if perms_lacking %} -

      {% blocktrans with escaped_object=object %}Deleting the {{ object_name }} '{{ escaped_object }}' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:{% endblocktrans %}

      -
        - {% for obj in perms_lacking %} -
      • {{ obj }}
      • - {% endfor %} -
      - {% endif %} - {% if protected %} -

      {% blocktrans with escaped_object=object %}Deleting the {{ object_name }} '{{ escaped_object }}' would require deleting the following protected related objects:{% endblocktrans %}

      -
        - {% for obj in protected %} -
      • {{ obj }}
      • - {% endfor %} -
      - {% endif %} -{% else %} -

      {% blocktrans with escaped_object=object %}Are you sure you want to delete the {{ object_name }} "{{ escaped_object }}"? All of the following related items will be deleted:{% endblocktrans %}

      -
        {{ deleted_objects|unordered_list }}
      -
      {% csrf_token %} -
      - - -
      -
      -{% endif %} +{% block breadcrumbs %} + {% include "admin/filer/breadcrumbs.html" with instance=object breadcrumbs_action="Delete" %} {% endblock %} diff --git a/filer/templates/admin/filer/delete_selected_files_confirmation.html b/filer/templates/admin/filer/delete_selected_files_confirmation.html index bba07c06f..5c9da677e 100644 --- a/filer/templates/admin/filer/delete_selected_files_confirmation.html +++ b/filer/templates/admin/filer/delete_selected_files_confirmation.html @@ -1,4 +1,4 @@ -{% extends "admin/filer/base_site.html" %} +{% extends "admin/delete_confirmation.html" %} {% load i18n %} {% block breadcrumbs %} @@ -6,44 +6,46 @@ {% endblock %} {% block content %} -{% if perms_lacking or protected %} - {% if perms_lacking %} -

      {% blocktrans %}Deleting the selected files and/or folders would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:{% endblocktrans %}

      -
        - {% for obj in perms_lacking %} -
      • {{ obj }}
      • + {% if perms_lacking or protected %} + {% if perms_lacking %} +

        {% blocktrans %}Deleting the selected files and/or folders would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:{% endblocktrans %}

        +
          + {% for obj in perms_lacking %} +
        • {{ obj }}
        • + {% endfor %} +
        + {% endif %} + {% if protected %} +

        {% blocktrans %}Deleting the selected files and/or folders would require deleting the following protected related objects:{% endblocktrans %}

        +
          + {% for obj in protected %} +
        • {{ obj }}
        • + {% endfor %} +
        + {% endif %} + {% else %} +

        {% blocktrans %}Are you sure you want to delete the selected files and/or folders? All of the following objects and their related items will be deleted:{% endblocktrans %}

        + {% for deletable_object in deletable_objects %} +
          {{ deletable_object|unordered_list }}
        {% endfor %} -
      +
      + {% csrf_token %} +
      + {% for f in files_queryset %} + + {% endfor %} + {% for f in folders_queryset %} + + {% endfor %} + {% if is_popup %} + + {% if select_folder %}{% endif %} + {% endif %} + + + {% translate "No, take me back" %} + +
      +
      {% endif %} - {% if protected %} -

      {% blocktrans %}Deleting the selected files and/or folders would require deleting the following protected related objects:{% endblocktrans %}

      -
        - {% for obj in protected %} -
      • {{ obj }}
      • - {% endfor %} -
      - {% endif %} -{% else %} -

      {% blocktrans %}Are you sure you want to delete the selected files and/or folders? All of the following objects and their related items will be deleted:{% endblocktrans %}

      - {% for deletable_object in deletable_objects %} -
        {{ deletable_object|unordered_list }}
      - {% endfor %} -
      {% csrf_token %} -
      - {% for f in files_queryset %} - - {% endfor %} - {% for f in folders_queryset %} - - {% endfor %} - {% if is_popup %} - - {% if select_folder %}{% endif %} - {% endif %} - - - -
      -
      -{% endif %} {% endblock %} diff --git a/filer/templates/admin/filer/dismiss_popup.html b/filer/templates/admin/filer/dismiss_popup.html new file mode 100644 index 000000000..af648bc66 --- /dev/null +++ b/filer/templates/admin/filer/dismiss_popup.html @@ -0,0 +1,8 @@ +{% extends "admin/filer/base_site.html" %} + +{% block extrahead %} + {{ block.super }} + +{% endblock %} diff --git a/filer/templates/admin/filer/fieldset.html b/filer/templates/admin/filer/fieldset.html new file mode 100644 index 000000000..9c6f7fb42 --- /dev/null +++ b/filer/templates/admin/filer/fieldset.html @@ -0,0 +1,41 @@ +
      + {% if fieldset.name %} +

      {{ fieldset.name }}

      + {% endif %} +
      + {% if fieldset.description %} +
      {{ fieldset.description|safe }}
      + {% endif %} + {% for line in fieldset %} +
      + + {% for field in line %} +
      + {% if line.fields|length != 1 and not field.is_readonly %}{{ field.errors }}{% endif %} + {% if field.is_checkbox %} +
      +
      {{ field.field }} {{ field.label_tag }}
      + {% else %} +
      {{ field.label_tag }}
      +
      + {% if field.is_readonly %} +

      {{ field.contents }}

      + {% else %} + {{ field.field }} + {% endif %} + {% if field.field.help_text %} + ? + {% endif %} + {% if not field.is_readonly and field.errors %} +
      + {{ field.errors }} +
      + {% endif %} +
      + {% endif %} +
      + {% endfor %} +
      + {% endfor %} +
      +
      diff --git a/filer/templates/admin/filer/file/change_form.html b/filer/templates/admin/filer/file/change_form.html new file mode 100644 index 000000000..601ed99c3 --- /dev/null +++ b/filer/templates/admin/filer/file/change_form.html @@ -0,0 +1,30 @@ +{% extends "admin/filer/change_form.html" %} +{% load i18n admin_modify static %} + +{% block extrahead %} + {{ block.super }} + + {# upload stuff #} + + +{% endblock %} + + +{% block object-tools %} + {% if change and not is_popup %} + + {% endif %} + {% include "admin/filer/tools/detail_info.html" %} +{% endblock %} + +{% block submit_buttons_bottom %} + {% if not is_readonly_file %} + {% submit_row %} + {% endif %} +{% endblock %} + diff --git a/filer/templates/admin/filer/file/popup_response.html b/filer/templates/admin/filer/file/popup_response.html new file mode 100644 index 000000000..625659f3d --- /dev/null +++ b/filer/templates/admin/filer/file/popup_response.html @@ -0,0 +1,10 @@ +{% extends "admin/filer/base_site.html" %} +{% load static %} + +{% block extrahead %} + {{ block.super }} + +{% endblock %} diff --git a/filer/templates/admin/filer/folder/change_form.html b/filer/templates/admin/filer/folder/change_form.html index 5684dcc99..7d850eb47 100644 --- a/filer/templates/admin/filer/folder/change_form.html +++ b/filer/templates/admin/filer/folder/change_form.html @@ -1,38 +1,41 @@ {% extends "admin/change_form.html" %} -{% load i18n admin_modify adminmedia filermedia %} -{% load url from future %} +{% load i18n admin_modify static filer_admin_tags %} {% block breadcrumbs %} - + {% endblock %} - {% block coltype %}{% if is_popup %}colM{% else %}colMS{% endif %}{% endblock %} + {% block object-tools %} -{% if change %}{% if not is_popup %} - -{% endif %}{% endif %} + {% if change and not is_popup %} + + {% endif %} {% endblock %} {% block after_field_sets %} -{% if is_popup and select_folder %}{% endif %} + {% filer_admin_context_hidden_formfields %} {% endblock %} -{% block sidebar %}{% if not is_popup %} - -{% endif %}{% endblock %} +{% block sidebar %} + {% if not is_popup %} + + {% endif %} +{% endblock %} diff --git a/filer/templates/admin/filer/folder/choose_copy_destination.html b/filer/templates/admin/filer/folder/choose_copy_destination.html index 1121a8833..38437b9de 100644 --- a/filer/templates/admin/filer/folder/choose_copy_destination.html +++ b/filer/templates/admin/filer/folder/choose_copy_destination.html @@ -1,45 +1,58 @@ -{% extends "admin/base_site.html" %} -{% load i18n adminmedia filer_admin_tags %} +{% extends "admin/filer/base_site.html" %} +{% load i18n static filer_admin_tags %} {% block breadcrumbs %} -{% include "admin/filer/breadcrumbs.html" %} + {% include "admin/filer/breadcrumbs.html" %} {% endblock %} -{% block extrastyle %}{{ block.super }}{% endblock %} +{% block extrastyle %} + {{ block.super }} + + +{% endblock %} + +{% block extrahead %} + {{ block.super }} + +{% endblock %} {% block content %} -{% if perms_lacking %} -

      {% blocktrans %}Your account doesn't have permissions to copy all of the selected files and/or folders.{% endblocktrans %}

      -{% else %} -{% if not destination_folders %} -

      {% blocktrans %}There are no destination folders available.{% endblocktrans %}

      -{% else %} -{% if not to_copy %} -

      {% blocktrans %}There are no files and/or folders available to copy.{% endblocktrans %}

      -{% else %} -

      {% blocktrans %}The following files and/or folders will be copied to a destination folder (retaining their tree structure):{% endblocktrans %}

      -
        {{ to_copy|unordered_list }}
      -
      {% csrf_token %} -
      - {% for f in files_queryset %} - - {% endfor %} - {% for f in folders_queryset %} - - {% endfor %} - - -

      -

      - {{ copy_form.as_p_with_help }} -

      -
      -
      -{% endif %} -{% endif %} -{% endif %} + {% if perms_lacking %} +

      {% blocktrans %}Your account doesn't have permissions to copy all of the selected files and/or folders.{% endblocktrans %}

      + + {% else %} + {% if not to_copy %} +

      {% blocktrans %}There are no files and/or folders available to copy.{% endblocktrans %}

      + + {% else %} +

      {% blocktrans %}The following files and/or folders will be copied to a destination folder (retaining their tree structure):{% endblocktrans %}

      +
        {{ to_copy|unordered_list }}
      +
      + {% csrf_token %} +
      + {% for f in files_queryset %} + + {% endfor %} + {% for f in folders_queryset %} + + {% endfor %} + + + + {% include "admin/filer/folder/destination_tree_field.html" %} + + {{ copy_form.as_p }} + + +
      +
      + {% endif %} + {% endif %} {% endblock %} diff --git a/filer/templates/admin/filer/folder/choose_images_resize_options.html b/filer/templates/admin/filer/folder/choose_images_resize_options.html index 69b46addf..a47df078a 100644 --- a/filer/templates/admin/filer/folder/choose_images_resize_options.html +++ b/filer/templates/admin/filer/folder/choose_images_resize_options.html @@ -1,41 +1,45 @@ {% extends "admin/base_site.html" %} -{% load i18n adminmedia filer_admin_tags %} +{% load i18n static %} {% block breadcrumbs %} -{% include "admin/filer/breadcrumbs.html" %} + {% include "admin/filer/breadcrumbs.html" %} {% endblock %} -{% block extrastyle %}{{ block.super }}{% endblock %} +{% block extrastyle %} + {{ block.super }} + +{% endblock %} {% block content %} -{% if perms_lacking %} -

      {% blocktrans %}Your account doesn't have permissions to resize all of the selected images.{% endblocktrans %}

      -{% else %} -{% if not to_resize %} -

      {% blocktrans %}There are no images available to resize.{% endblocktrans %}

      -{% else %} -

      {% blocktrans %}The following images will be resized:{% endblocktrans %}

      -
        {{ to_resize|unordered_list }}
      -
      {% csrf_token %} -
      - {% for f in files_queryset %} - - {% endfor %} - {% for f in folders_queryset %} - - {% endfor %} - - - {% if cmsplugin_enabled %} -

      {% blocktrans %}Choose an existing thumbnail option or enter resize parameters:{% endblocktrans %}

      + {% if perms_lacking %} +

      {% blocktrans %}Your account doesn't have permissions to resize all of the selected images.{% endblocktrans %}

      {% else %} -

      {% blocktrans %}Choose resize parameters:{% endblocktrans %}

      - {% endif %} - {{ resize_form.as_p_with_help }} -

      {% blocktrans %}Warning: Images will be resized in-place and originals will be lost. Maybe first make a copy of them to retain the originals.{% endblocktrans %}

      -

      -
      -
      -{% endif %} -{% endif %} + {% if not to_resize %} +

      {% blocktrans %}There are no images available to resize.{% endblocktrans %}

      + {% else %} +

      {% blocktrans %}The following images will be resized:{% endblocktrans %}

      +
        {{ to_resize|unordered_list }}
      +
      {% csrf_token %} +
      + {% for f in files_queryset %} + + {% endfor %} + {% for f in folders_queryset %} + + {% endfor %} + + +

      {% blocktrans %}Choose an existing thumbnail option or enter resize parameters:{% endblocktrans %}

      + {% for fieldset in resize_form.admin_form %} + {% include "admin/includes/fieldset.html" %} + {% endfor %} +

      {% blocktrans %}Warning: Images will be resized in-place and originals will be lost. Maybe first make a copy of them to retain the originals.{% endblocktrans %}

      + +
      + +
      +
      +
      + {% endif %} + {% endif %} {% endblock %} diff --git a/filer/templates/admin/filer/folder/choose_move_destination.html b/filer/templates/admin/filer/folder/choose_move_destination.html index d79774b83..93b875368 100644 --- a/filer/templates/admin/filer/folder/choose_move_destination.html +++ b/filer/templates/admin/filer/folder/choose_move_destination.html @@ -1,44 +1,55 @@ -{% extends "admin/base_site.html" %} -{% load i18n adminmedia filer_admin_tags %} +{% extends "admin/filer/base_site.html" %} +{% load i18n static filer_admin_tags %} {% block breadcrumbs %} -{% include "admin/filer/breadcrumbs.html" %} + {% include "admin/filer/breadcrumbs.html" %} {% endblock %} -{% block extrastyle %}{{ block.super }}{% endblock %} +{% block extrastyle %} + {{ block.super }} + + +{% endblock %} + +{% block extrahead %} + {{ block.super }} + +{% endblock %} {% block content %} -{% if perms_lacking %} -

      {% blocktrans %}Your account doesn't have permissions to move all of the selected files and/or folders.{% endblocktrans %}

      -{% else %} -{% if not destination_folders %} -

      {% blocktrans %}There are no destination folders available.{% endblocktrans %}

      -{% else %} -{% if not to_move %} -

      {% blocktrans %}There are no files and/or folders available to move.{% endblocktrans %}

      -{% else %} -

      {% blocktrans %}The following files and/or folders will be moved to a destination folder (retaining their tree structure):{% endblocktrans %}

      -
        {{ to_move|unordered_list }}
      -
      {% csrf_token %} -
      - {% for f in files_queryset %} - - {% endfor %} - {% for f in folders_queryset %} - - {% endfor %} - - -

      -

      -

      -
      -
      -{% endif %} -{% endif %} -{% endif %} + {% if perms_lacking %} +

      {% blocktrans %}Your account doesn't have permissions to move all of the selected files and/or folders.{% endblocktrans %}

      + + {% else %} + {% if not to_move %} +

      {% blocktrans %}There are no files and/or folders available to move.{% endblocktrans %}

      + + {% else %} +

      {% blocktrans %}The following files and/or folders will be moved to a destination folder (retaining their tree structure):{% endblocktrans %}

      +
        {{ to_move|unordered_list }}
      +
      {% csrf_token %} +
      + {% for f in files_queryset %} + + {% endfor %} + {% for f in folders_queryset %} + + {% endfor %} + + + + {% include "admin/filer/folder/destination_tree_field.html" %} + + +
      +
      + {% endif %} + {% endif %} {% endblock %} diff --git a/filer/templates/admin/filer/folder/choose_rename_format.html b/filer/templates/admin/filer/folder/choose_rename_format.html index c86d6058e..fae8ea1b7 100644 --- a/filer/templates/admin/filer/folder/choose_rename_format.html +++ b/filer/templates/admin/filer/folder/choose_rename_format.html @@ -1,59 +1,65 @@ {% extends "admin/base_site.html" %} -{% load i18n adminmedia filer_admin_tags %} +{% load i18n static %} {% block breadcrumbs %} -{% include "admin/filer/breadcrumbs.html" %} + {% include "admin/filer/breadcrumbs.html" %} {% endblock %} -{% block extrastyle %}{{ block.super }}{% endblock %} +{% block extrastyle %} + {{ block.super }} + +{% endblock %} {% block content %} -{% if perms_lacking %} -

      {% blocktrans %}Your account doesn't have permissions to rename all of the selected files.{% endblocktrans %}

      -{% else %} -{% if not to_rename %} -

      {% blocktrans %}There are no files available to rename.{% endblocktrans %}

      -{% else %} -

      {% blocktrans %}The following files will be renamed (they will stay in their folders and keep original filename, only displayed filename will be changed):{% endblocktrans %}

      -
        {{ to_rename|unordered_list }}
      -
      {% csrf_token %} -
      - {% for f in files_queryset %} - - {% endfor %} - {% for f in folders_queryset %} - - {% endfor %} - - - {{ rename_form.as_p_with_help }} -
      -

      Rename format is in Python % operator format using dictionary of possible values:

      -
      -
      original_filename
      -
      original_basename
      -
      Original filename without possible file extension.
      -
      original_extension
      -
      current_filename
      -
      current_basename
      -
      Current filename without possible file extension.
      -
      current_extension
      -
      current_folder
      -
      Name of the folder the file is currently in.
      -
      counter
      -
      Renaming sequence counter in the current folder (1-based).
      -
      global_counter
      -
      Renaming squence counter for all files currently renaming (1-based).
      -
      -

      Examples:

      -
        -
      • Prefix %(current_filename)s
      • -
      • Image %(counter)03d
      • -
      -
      -

      -
      -
      -{% endif %} -{% endif %} + {% if perms_lacking %} +

      {% blocktrans %}Your account doesn't have permissions to rename all of the selected files.{% endblocktrans %}

      + {% else %} + {% if not to_rename %} +

      {% blocktrans %}There are no files available to rename.{% endblocktrans %}

      + {% else %} +

      {% blocktrans %}The following files will be renamed (they will stay in their folders and keep original filename, only displayed filename will be changed):{% endblocktrans %}

      +
        {{ to_rename|unordered_list }}
      +
      + {% csrf_token %} +
      + {% for f in files_queryset %} + + {% endfor %} + {% for f in folders_queryset %} + + {% endfor %} + + + {{ rename_form.as_p }} +
      +

      Rename format is in Python % operator format using dictionary of possible values:

      +
      +
      original_filename
      +
      original_basename
      +
      Original filename without possible file extension.
      +
      original_extension
      +
      current_filename
      +
      current_basename
      +
      Current filename without possible file extension.
      +
      current_extension
      +
      current_folder
      +
      Name of the folder the file is currently in.
      +
      counter
      +
      Renaming sequence counter in the current folder (1-based).
      +
      global_counter
      +
      Renaming squence counter for all files currently renaming (1-based).
      +
      +

      Examples:

      +
        +
      • Prefix %(current_filename)s
      • +
      • Image %(counter)03d
      • +
      +
      +

      + +

      +
      +
      + {% endif %} + {% endif %} {% endblock %} diff --git a/filer/templates/admin/filer/folder/destination_field.html b/filer/templates/admin/filer/folder/destination_field.html new file mode 100644 index 000000000..c76bd2895 --- /dev/null +++ b/filer/templates/admin/filer/folder/destination_field.html @@ -0,0 +1,54 @@ +{% load i18n filermedia sekizai_tags%} + +

      + +Select a folder below. + +

      +
      +{% addtoblock "js" %} + + + + + +{% endaddtoblock %} diff --git a/filer/templates/admin/filer/folder/destination_tree_field.html b/filer/templates/admin/filer/folder/destination_tree_field.html new file mode 100644 index 000000000..beb9a7ba7 --- /dev/null +++ b/filer/templates/admin/filer/folder/destination_tree_field.html @@ -0,0 +1,220 @@ +{% load i18n %} +

      + + {% trans "Select a folder below." %} + +

      +
      + + + + + diff --git a/filer/templates/admin/filer/folder/directory_listing.html b/filer/templates/admin/filer/folder/directory_listing.html index 0de1a3e74..c4a336a04 100644 --- a/filer/templates/admin/filer/folder/directory_listing.html +++ b/filer/templates/admin/filer/folder/directory_listing.html @@ -1,98 +1,267 @@ {% extends "admin/filer/base_site.html" %} -{% load adminmedia filer_admin_tags filermedia i18n %} -{% load url from future %} +{% load i18n static filer_admin_tags %} -{% block extrahead %}{{ block.super }} -{# upload stuff #} -{{ media.js }} - - - - - - -{% if action_form %}{% if actions_on_top or actions_on_bottom %} - -{% endif %}{% endif %} -{% endblock %} +{% block coltype %}{% endblock %} +{% block bodyclass %}{{ block.super }} change-list filebrowser{% endblock %} -{% block coltype %}colMS{% endblock %} -{% block bodyclass %}change-list filebrowser{% endblock %} +{% block extrastyle %} + {{ block.super }} -{% block extrastyle %}{{ block.super }} - -{{ media.css }} -{% if action_form %} - {% url 'admin:jsi18n' as jsi18nurl %} - -{% endif %} -{% if query.pop %} - -{% endif %} -{% if not actions_on_top and not actions_on_bottom %} - -{% endif %} + {{ media.css }} + {% if action_form %} + {% url 'admin:jsi18n' as jsi18nurl %} + + {% endif %} + {% if query.pop %} + + {% endif %} {% endblock %} {% block breadcrumbs %} -{% with folder as instance %} -{% include "admin/filer/breadcrumbs.html" %} -{% endwith %} + {% if not is_popup %} + + {% endif %} {% endblock %} - {% block sidebar %} - {% endblock %} +{% block content_title %} +

       

      +{% endblock %} + +{% block object-tools %} +{% endblock %} -{% block content_title %}

       

      {% endblock %} {% block content %} -
      - - -
      + +
      {% include "admin/filer/tools/search_form.html" %} - {% if not folder.is_root %} -

      {% if folder.parent %}{% else %}{% endif %} - {% trans {{ folder.name }} - ({% blocktrans count folder.children_count as counter %}1 folder{% plural %}{{ counter }} folders{% endblocktrans %}, {% blocktrans count folder.file_count as counter %}1 file{% plural %}{{ counter }} files{% endblocktrans %}) - - {% if is_popup %} - {% if select_folder and folder.file_type == 'Folder' %} {% endif %} - {% else %}{% trans "Change" %}{% endif %} - -

      - {% else %}{% if folder.is_smart_folder %} -

      - {% trans {{ folder.name }} -

      - {% endif %} - {% endif %} -
      {% csrf_token %} - {% if is_popup %}{% endif %} - {% if action_form and actions_on_top and paginator.count and not select_folder and not is_popup %}{% filer_actions %}{% endif %} - {% include "admin/filer/folder/directory_table.html" %} - {% if action_form and actions_on_bottom and paginator.count and not select_folder and not is_popup %}{% filer_actions %}{% endif %} -
      +
      -
      - {% endblock %} diff --git a/filer/templates/admin/filer/folder/directory_table.html b/filer/templates/admin/filer/folder/directory_table.html index 6a7d82679..aa0c9b7c6 100644 --- a/filer/templates/admin/filer/folder/directory_table.html +++ b/filer/templates/admin/filer/folder/directory_table.html @@ -1,78 +1,71 @@ {% load i18n %} -{% load adminmedia admin_list filermedia filer_tags %} -{% load url from future %} - -
      - +{% load admin_list filermedia filer_tags filer_admin_tags %} +{% spaceless %} +
      +
      - {% if paginator.count and not select_folder and not is_popup %}{% endif %} + {% if paginator.count and not select_folder and not is_popup %}{% endif %} - + + {% if not is_popup and folder.is_root and not show_result_count %} + {% if paginated_items.number == 1 %} + {% for subfolder in folder.virtual_folders %} + + {% include "admin/filer/folder/subfolder_row.html" %} + + {% endfor %} + {% endif %} + {% endif %} {% for item in paginated_items.object_list %} - {% if item.file_type == 'Folder' or item.file_type == 'DummyFolder' %}{% with item as subfolder%} + {% if item.file_type == 'Folder' or item.file_type == 'DummyFolder' %} + {% with item as subfolder %} - - - - - - + {% include "admin/filer/folder/subfolder_row.html" %} - {% endwith %}{% endif %} - {% if item.file_type == 'File' or item.file_type == 'Image' %}{% with item as file %} + {% endwith %} + {% endif %} + {% if item.file_type == 'File' or item.file_type == 'Image' or item.file_type == 'Archive' %} + {% with item as file %} - - - - - - + {% include "admin/filer/folder/file_row.html" %} - {% endwith %}{% endif %} + {% endwith %} + {% endif %} {% endfor %} - {% if not folder.is_root %}{% ifequal folder.item_count 0 %} + + {% if not folder.is_root %} + {% if folder.item_count == 0 %} - - - - {% endifequal %}{% endif %} + + + + {% endif %} + {% endif %}
         {% trans 'Name' %}
      {% if select_folder and item.file_type == 'Folder' %} {% else %}{% if action_form and item.pk and not is_popup %}{% endif %}{% endif %}{% trans - {% if item.file_type == 'Folder' %} - {% trans "Change" %} - {% endif %} -
      {{ subfolder.name }}{% if not subfolder.is_root %} ({% blocktrans count subfolder.children_count as counter %}1 folder{% plural %}{{ counter }} folders{% endblocktrans %}, {% blocktrans count subfolder.file_count as counter %}1 file{% plural %}{{ counter }} files{% endblocktrans %}){% endif %}
      -
      {% trans "Owner" %}: {{ subfolder.owner|default:"n/a" }}
      -
      {% if is_popup and not select_folder %} {% else %}{% if action_form and not is_popup %}{% endif %}{% endif %}{{ file.default_alt_text }} - {% trans "Delete" %} - {% trans "Change" %} -
      {{ file.label }} ({{ file.size|filesize:"auto1000long" }}{% ifequal file.file_type "Image" %}, {{ file.width }}x{{ file.height }} px{% endifequal %})
      -
      {% trans "Owner" %}: {{ file.owner|default:"n/a" }}
      - {% if enable_permissions %}
      {% trans "Permissions" %}: {% if file.is_public %}{% trans "disabled" %}{% else %}{% trans "enabled" %}{% endif %}
      {% endif %} - {# {% if file.has_all_mandatory_data %}
      0 {% trans "has all mandatory metadata" %}
      {% else %}
      1 {% trans "missing metadata!" %}
      {% endif %} #} -
      - -
      {% trans "there are no files or subfolders" %}
      {% trans "there are no files or subfolders" %}
      -

      - {% if paginated_items.has_previous %} - {% trans "previous" %} - {% endif %} +

      +
      + {% if paginated_items.has_previous %} + {% trans "previous" %} + {% endif %} - - {% blocktrans with paginated_items.number as number and paginated_items.paginator.num_pages as num_pages %} - Page {{ number }} of {{ num_pages }}. - {% endblocktrans %} - + + {% blocktrans with paginated_items.number as number and paginated_items.paginator.num_pages as num_pages %} + Page {{ number }} of {{ num_pages }} + {% endblocktrans %} + - {% if paginated_items.has_next %} - {% trans "next" %} - {% endif %} -

      + {% if paginated_items.has_next %} + {% trans "next" %} + {% endif %} +
      +
      +{% endspaceless %} diff --git a/filer/templates/admin/filer/folder/directory_table_list.html b/filer/templates/admin/filer/folder/directory_table_list.html new file mode 100644 index 000000000..54647e5fa --- /dev/null +++ b/filer/templates/admin/filer/folder/directory_table_list.html @@ -0,0 +1,256 @@ +{% load i18n l10n admin_list filer_tags filer_admin_tags static thumbnail %} +
      + diff --git a/filer/templates/admin/filer/folder/directory_thumbnail_list.html b/filer/templates/admin/filer/folder/directory_thumbnail_list.html new file mode 100644 index 000000000..b7a3fe91f --- /dev/null +++ b/filer/templates/admin/filer/folder/directory_thumbnail_list.html @@ -0,0 +1,228 @@ +{% load i18n l10n admin_list filer_tags filer_admin_tags static thumbnail %} +
      + diff --git a/filer/templates/admin/filer/folder/file_row.html b/filer/templates/admin/filer/folder/file_row.html new file mode 100644 index 000000000..e8a93e716 --- /dev/null +++ b/filer/templates/admin/filer/folder/file_row.html @@ -0,0 +1,36 @@ +{% load i18n filermedia filer_tags filer_admin_tags %} + + + {% if is_popup and not select_folder %} + + {% else %} + {% if action_form and not is_popup and not file|is_readonly_for_user:user %} + + {% endif %} + {% endif %} + + + + {{ file.default_alt_text }} + + +{% if not is_popup and not file|is_restricted_for_user:user %} + + {% trans "Delete" %} + + {% trans "Change" %} + {% endif %} +
      + + {% if show_result_count %}{{ file.pretty_logical_path }}{% else %}{{ file.label }}{% endif %} + + ({{ file.size|filesize:"auto1000long" }}{% if file.file_type == "Image" %}, {{ file.width }}x{{ file.height }} px{% endif %}) +
      +
      {% trans "Owner" %}: {% firstof file.owner.email file.owner.username "n/a" %}
      + {# {% if file.has_all_mandatory_data %}
      0 {% trans "has all mandatory metadata" %}
      {% else %}
      1 {% trans "missing metadata!" %}
      {% endif %} #} + + + {% if not is_popup and not file|is_restricted_for_user:user %} + + {% endif %} + diff --git a/filer/templates/admin/filer/folder/legacy_listing.html b/filer/templates/admin/filer/folder/legacy_listing.html new file mode 100644 index 000000000..50cc1af34 --- /dev/null +++ b/filer/templates/admin/filer/folder/legacy_listing.html @@ -0,0 +1,267 @@ +{% extends "admin/filer/base_site.html" %} +{# Used for django < 5.2 with lagacy object-tools blocks #} +{# Customized templates will need to be updated for django >= 5.2 #} +{# The object-tools block has been renamed filer-tools for django >= 5.2 #} + +{% load i18n static filer_admin_tags %} + +{% block coltype %}{% endblock %} +{% block bodyclass %}{{ block.super }} change-list filebrowser{% endblock %} + +{% block extrastyle %} + {{ block.super }} + + {{ media.css }} + {% if action_form %} + {% url 'admin:jsi18n' as jsi18nurl %} + + {% endif %} + {% if query.pop %} + + {% endif %} +{% endblock %} + +{% block breadcrumbs %} + {% if not is_popup %} + + {% endif %} +{% endblock %} + +{% block sidebar %} + {% include "admin/filer/tools/clipboard/clipboard.html" %} +{% endblock %} + +{% block content_title %} +

       

      +{% endblock %} + +{% block content %} + +
      + {% include "admin/filer/tools/search_form.html" %} + +
      +{% endblock %} \ No newline at end of file diff --git a/filer/templates/admin/filer/folder/list_type_switcher.html b/filer/templates/admin/filer/folder/list_type_switcher.html new file mode 100644 index 000000000..ebf95c4e4 --- /dev/null +++ b/filer/templates/admin/filer/folder/list_type_switcher.html @@ -0,0 +1 @@ + diff --git a/filer/templates/admin/filer/folder/new_folder_form.html b/filer/templates/admin/filer/folder/new_folder_form.html index eb0e8dc1a..f9ff43b7d 100644 --- a/filer/templates/admin/filer/folder/new_folder_form.html +++ b/filer/templates/admin/filer/folder/new_folder_form.html @@ -1,37 +1,38 @@ {% extends "admin/change_form.html" %} -{% load i18n %} +{% load i18n filer_admin_tags %} + +{% block title %}{% translate "Add new" %} {% translate "folder" %} | {{ site_title|default:_('Django site admin') }}{% endblock %} + {% block content %} -

      {% trans "Add new" %} {% trans "folder" %}

      -
      -
      - {% csrf_token %} -
      - - {% if select_folder %}{% endif %} - {% if new_folder_form.errors %} -

      - {% blocktrans count new_folder_form.errors|length as counter %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktrans %} -

      - {{ new_folder_form.non_field_errors }} - {% endif %} -
      -
      - {{ new_folder_form.errors.name.as_ul }} -
      - {% for field in new_folder_form %} - {{ field }} - {% endfor %} -
      +

      {% translate "Add new" %} {% translate "folder" %}

      +
      + + {% csrf_token %} +
      + {% filer_admin_context_hidden_formfields %} + {% if new_folder_form.errors %} +

      + {% blocktrans count new_folder_form.errors|length as counter %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktrans %} +

      + {{ new_folder_form.non_field_errors }} + {% endif %} +
      +
      + {{ new_folder_form.errors.name.as_ul }} +
      + {% for field in new_folder_form %} + {{ field }} + {% endfor %} +
      +
      +
      +
      + +
      +
      -
      -
      - -
      - -
      -
      -
      - - -
      + +
      {% endblock %} diff --git a/filer/templates/admin/filer/folder/subfolder_row.html b/filer/templates/admin/filer/folder/subfolder_row.html new file mode 100644 index 000000000..dac7f36e9 --- /dev/null +++ b/filer/templates/admin/filer/folder/subfolder_row.html @@ -0,0 +1,31 @@ +{% load i18n filer_admin_tags %} + + {% if select_folder and subfolder.file_type == 'Folder' %} + + {% else %} + {% if action_form and subfolder.pk and not is_popup and not subfolder|is_readonly_for_user:user %} + + + {% endif %} + {% endif %} + + + + {% trans + + + + {% if subfolder.file_type == 'Folder' and not is_popup and subfolder|can_change_folder:user %} + {% trans "Change" %} + {% endif %} +
      + + {% if show_result_count %}{{ subfolder.pretty_logical_path }}{% else %}{{ subfolder.name }}{% endif %} + {% if not subfolder.is_root %} + ({% blocktrans count subfolder.children.count as counter %}1 folder{% plural %}{{ counter }} folders{% endblocktrans %}, {% blocktrans count subfolder.files.count as counter %}1 file{% plural %}{{ counter }} files{% endblocktrans %}) + {% endif %} +
      + {{ subfolder.get_folder_type_display }}{% if subfolder.site %}: {{subfolder.site}}{%endif%} +
      {% trans "Owner" %}: {% firstof subfolder.owner.email subfolder.owner.username "n/a" %}
      + + diff --git a/filer/templates/admin/filer/image/change_form.html b/filer/templates/admin/filer/image/change_form.html index 6b38faf04..2c564487a 100644 --- a/filer/templates/admin/filer/image/change_form.html +++ b/filer/templates/admin/filer/image/change_form.html @@ -1,24 +1,22 @@ {% extends "admin/filer/change_form.html" %} -{% load i18n admin_modify adminmedia %} +{% load i18n admin_modify static %} +{% block extrahead %} + {{ block.super }} -{% block object-tools %} -{% if change %}{% if not is_popup %} - -{% endif %}{% endif %} + {# upload stuff #} + + {% endblock %} -{% block file_sidebar %} - -{{ block.super }} -{% endblock %} \ No newline at end of file +{% block object-tools %} + {% if change and not is_popup %} + + {% endif %} + {% include "admin/filer/tools/detail_info.html" %} +{% endblock %} diff --git a/filer/templates/admin/filer/image/expand.html b/filer/templates/admin/filer/image/expand.html new file mode 100644 index 000000000..891ae07d0 --- /dev/null +++ b/filer/templates/admin/filer/image/expand.html @@ -0,0 +1,28 @@ + + + + + + + + + diff --git a/filer/templates/admin/filer/image/full_size_preview.html b/filer/templates/admin/filer/image/full_size_preview.html new file mode 100644 index 000000000..1dacf0450 --- /dev/null +++ b/filer/templates/admin/filer/image/full_size_preview.html @@ -0,0 +1,17 @@ +{% load i18n filer_admin_tags filermedia %} + + + Full size preview {{ image.actual_name }} + + + + + + + +
      + Go back + +
      + + diff --git a/filer/templates/admin/filer/submit_line.html b/filer/templates/admin/filer/submit_line.html new file mode 100644 index 000000000..04f9428e4 --- /dev/null +++ b/filer/templates/admin/filer/submit_line.html @@ -0,0 +1,8 @@ +{% load i18n admin_urls %} +
      + {% if show_delete_link and original.pk %}{% trans "Delete" %}{% endif %} + {% if show_save_as_new %}{%endif%} + {% if show_save_and_add_another %}{% endif %} + {% if show_save_and_continue %}{% endif %} + {% if show_save %}{% endif %} +
      diff --git a/filer/templates/admin/filer/templatetags/file_icon.html b/filer/templates/admin/filer/templatetags/file_icon.html new file mode 100644 index 000000000..39a5f4430 --- /dev/null +++ b/filer/templates/admin/filer/templatetags/file_icon.html @@ -0,0 +1,38 @@ +{% load i18n %} +{% if sidebar_image_ratio %} +
      +{% endif %} +{% if download_url %} + {% if mime_maintype == 'audio' %} + + {% elif mime_maintype == 'video' %} + + {% else %} + {{ alt_text }} + {% endif %} +{% else %} + {{ alt_text }} +{% endif %} +{% if sidebar_image_ratio %} +
      + +
      +
      +{% endif %} diff --git a/filer/templates/admin/filer/tools/clipboard/clipboard.html b/filer/templates/admin/filer/tools/clipboard/clipboard.html index d0a4b0176..4dce738b1 100644 --- a/filer/templates/admin/filer/tools/clipboard/clipboard.html +++ b/filer/templates/admin/filer/tools/clipboard/clipboard.html @@ -1,47 +1,55 @@ -{% load thumbnail i18n %} -{% load url from future %} +{% load i18n filer_admin_tags %} {% for clipboard in user.filer_clipboards.all %} - - - - - - - - - - {% if clipboard.files.count %}{% with clipboard.files.all as items %} - {% include "admin/filer/tools/clipboard/clipboard_item_rows.html" %} - {% endwith %} - {% else %} - - - - {% endif %} - -
      {% trans "Clipboard" %}
      -
      - {% csrf_token %} - - - - {% if is_popup %}{% endif %} - {% if select_folder %}{% endif %} - -
      -
      {% csrf_token %} - - - {% if is_popup %}{% endif %} - {% if select_folder %}{% endif %} - -
      {% comment %} -
      {% csrf_token %} - - - {% if is_popup %}{% endif %} - -
      {% endcomment %} -
      {% trans "the clipboard is empty" %}
      + {% endfor %} diff --git a/filer/templates/admin/filer/tools/clipboard/clipboard_item_rows.html b/filer/templates/admin/filer/tools/clipboard/clipboard_item_rows.html index 89209e177..9d46e7fbe 100644 --- a/filer/templates/admin/filer/tools/clipboard/clipboard_item_rows.html +++ b/filer/templates/admin/filer/tools/clipboard/clipboard_item_rows.html @@ -1,13 +1,19 @@ -{% load thumbnail i18n %}{% if items %} -{% for generic_item in items %}{% with generic_item as item %} - - {{ item.default_alt_text }} - {{ item.label }} - - -{% endwith %}{% endfor %}{% else %} - - - {% trans "upload failed" %} - - {% endif %} \ No newline at end of file +{% load i18n %} + +{% if items %} + {% for generic_item in items %} + {% with generic_item as item %} + + {{ item.default_alt_text }} + {{ item.label }} + + + {% endwith %} + {% endfor %} +{% else %} + + + {% translate "upload failed" %} + + +{% endif %} diff --git a/filer/templates/admin/filer/tools/detail_info.html b/filer/templates/admin/filer/tools/detail_info.html new file mode 100644 index 000000000..1e18f34ea --- /dev/null +++ b/filer/templates/admin/filer/tools/detail_info.html @@ -0,0 +1,55 @@ +{% load filer_admin_tags i18n static %} +
      +
      +
      +
      + {% file_icon original detail=True %} +
      + {% if original.file.exists %} + +   + {% translate "Download" %} + + {% if expand_image_url %} + + {% translate "Expand" %}  + + + {% endif %} + {% else %} + {% translate "File is missing" %} + {% endif %} +
      +
      +
      +
      + {% if original.file_type or original.modified_at or original.uploaded_at or original.width or original.height or original.size %} +
      + {% if original.file_type %} +
      {% translate "Type" %}
      +
      {{ original.extension|upper }} {{ original.file_type }} ({{ original.mime_type }})
      + {% endif %} + {% if original.width or original.height %} +
      {% translate "Size" %}
      +
      {{ original.width|floatformat }}x{{ original.height|floatformat }} px
      + {% endif %} + {% if original.size %} +
      {% translate "File-size" %}
      +
      {{ original.size|filesizeformat }}
      + {% endif %} + {% if original.modified_at %} +
      {% translate "Modified" %}
      +
      {{ original.modified_at }}
      + {% endif %} + {% if original.uploaded_at %} +
      {% translate "Created" %}
      +
      {{ original.uploaded_at }}
      + {% endif %} + {% if original.owner %} +
      {% translate "Owner" %}
      +
      {{ original.owner }}
      + {% endif %} +
      + {% endif %} +
      +
      diff --git a/filer/templates/admin/filer/tools/search_form.html b/filer/templates/admin/filer/tools/search_form.html index 6a6a93649..cf3f98976 100644 --- a/filer/templates/admin/filer/tools/search_form.html +++ b/filer/templates/admin/filer/tools/search_form.html @@ -1,27 +1,9 @@ -{% load adminmedia filermedia filer_admin_tags %} -{% load i18n %} -
      -
      - +{% load i18n static filer_admin_tags %} + +{% if show_result_count %} +
      + ({% translate "found" %} {% blocktrans count folder_children|length as counter %}{{ counter }} folder{% plural %}{{ counter }} folders{% endblocktrans %} {% translate "and" %} + {% blocktrans count folder_files|length as counter %}{{ counter }} file{% plural %}{{ counter }} files{% endblocktrans %}) + {% translate "cancel search" %}
      -
      -
      - +{% endif %} diff --git a/filer/templates/admin/filer/tools/upload_button_js.html b/filer/templates/admin/filer/tools/upload_button_js.html index 507e413b0..5284d9efe 100644 --- a/filer/templates/admin/filer/tools/upload_button_js.html +++ b/filer/templates/admin/filer/tools/upload_button_js.html @@ -1,5 +1,4 @@ -{% load i18n admin_modify adminmedia filermedia %} -{% load url from future %} +{% load i18n admin_modify filermedia %} +
      {% csrf_token %} +
      + + + + + + + + + + {% for item in paginated_items.object_list %} + {% if item.file_type == 'Folder' %} + {% with item as subfolder %} + + {% include "admin/filer/trash/subfolder_row.html" %} + + {% endwith %} + {% endif %} + + {% if item.file_type == 'File' or item.file_type == 'Image' or item.file_type == 'Archive' %} + {% with item as file %} + + {% include "admin/filer/trash/file_row.html" %} + + {% endwith %} + {% endif %} + {% empty %} + + + + {% endfor %} + +
       {% trans 'Path' %}{% trans 'Deletion Date' %}
      {% trans "there are no files or subfolders" %}
      +
      +
      + {% if paginated_items.has_previous %} + {% trans "previous" %} + {% endif %} + + + {% blocktrans with paginated_items.number as number and paginated_items.paginator.num_pages as num_pages %} + Page {{ number }} of {{ num_pages }}. + {% endblocktrans %} + + + {% if paginated_items.has_next %} + {% trans "next" %} + {% endif %} +
      +
      +
      + +
      +
      +
      +{% endspaceless %} +{% endblock %} diff --git a/filer/templates/admin/filer/trash/file_row.html b/filer/templates/admin/filer/trash/file_row.html new file mode 100644 index 000000000..a8c712209 --- /dev/null +++ b/filer/templates/admin/filer/trash/file_row.html @@ -0,0 +1,16 @@ +{% load i18n filermedia filer_admin_tags filer_tags %} + + + {{ file.default_alt_text }} + + + +
      + {{ file|pretty_display }} + ({{ file.size|filesize:"auto1000long" }}{% if file.file_type == "Image" %}, {{ file.width }}x{{ file.height }} px{% endif %}) +
      + {% trans "Owner" %}: {% firstof file.owner.email file.owner.username "n/a" %} + + + {{ file.deleted_at }} + diff --git a/filer/templates/admin/filer/trash/item_restore.html b/filer/templates/admin/filer/trash/item_restore.html new file mode 100644 index 000000000..75dfc2c24 --- /dev/null +++ b/filer/templates/admin/filer/trash/item_restore.html @@ -0,0 +1,146 @@ +{% extends "admin/filer/base_site.html" %} +{% load filer_admin_tags i18n filermedia %} +{% block breadcrumbs %} + +{% endblock %} + +{% block extrahead %}{{ block.super }} +{# upload stuff #} +{{ media.js }} + + +{% endblock %} + +{% block extrastyle %} +{{ block.super }} +{{ media.css }} + +{% endblock %} + +{% block content %} +{% spaceless %} +
      +
      LOADING ...
      +
      +
      +{% csrf_token %} + +{% if descendants %} +
        + {% for descendant in descendants %} +
      • + {{ descendant|pretty_display }} + +
          + {% for file in descendant.trashed_files %} +
        • + {{file.actual_name}} + +
        • + {% endfor %} +
        +
      • + {% endfor %} +
      +{% else %} +
        +
      • + {{current_item.actual_name}} + +
      • +
      +{% endif %} + +
      + + + +
      +
      +
      +{% endspaceless %} +{% endblock %} diff --git a/filer/templates/admin/filer/trash/subfolder_row.html b/filer/templates/admin/filer/trash/subfolder_row.html new file mode 100644 index 000000000..a01a496b2 --- /dev/null +++ b/filer/templates/admin/filer/trash/subfolder_row.html @@ -0,0 +1,15 @@ +{% load i18n filer_admin_tags %} + +{% trans + + +
      + {{ subfolder|pretty_display }} + ({% blocktrans count subfolder.trashed_children_count as counter %}1 folder{% plural %}{{ counter }} folders{% endblocktrans %}, {% blocktrans count subfolder.trashed_file_count as counter %}1 file{% plural %}{{ counter }} files{% endblocktrans %}) +
      + {{ subfolder.get_folder_type_display }}{% if subfolder.site %}: {{subfolder.site}}{%endif%} +
      {% trans "Owner" %}: {% firstof subfolder.owner.email subfolder.owner.username "n/a" %}
      + + + {{ subfolder.deleted_at }} + diff --git a/filer/templates/admin/filer/widgets/admin_file.html b/filer/templates/admin/filer/widgets/admin_file.html index 88c099d87..65f4d9994 100644 --- a/filer/templates/admin/filer/widgets/admin_file.html +++ b/filer/templates/admin/filer/widgets/admin_file.html @@ -1,35 +1,62 @@ -{% load i18n filer_admin_tags %}{% spaceless %} -{% if object %} - {% if object.icons.32 %} - {{ object.label }} -  {{ object.label }} - {% else %} - {% trans 'file missing' %} -  {% trans 'file missing' %} - {% endif %} -{% else %} - {% trans 'no file selected' %} -   -{% endif %} - - {% trans 'Lookup' %} - - -
      -{{ hidden_input }} - +{% load i18n filer_admin_tags static %} + +{% spaceless %} +
      +
      + + + +
      +
      +
      + {% translate "or drop your file here" %} +
      + + + {% if object %} + {% if object.file.exists %} + {% file_icon object detail="thumbnail" %} +  {{ object.label }} + {% else %} + {% file_icon object %} +  {% translate 'File is missing' %} + {% endif %} + {% else %} + +   + {% endif %} + + + + + + + + + + + {% translate 'Choose File' %} + + + +
      + + +
      +
      +
      {% endspaceless %} diff --git a/filer/templates/admin/filer/widgets/admin_file_custom.html b/filer/templates/admin/filer/widgets/admin_file_custom.html new file mode 100644 index 000000000..885fa5b8b --- /dev/null +++ b/filer/templates/admin/filer/widgets/admin_file_custom.html @@ -0,0 +1,55 @@ +{% comment "Template for file widget with customizable preview" %} + Changes made here should also be considered for admin_file.html. +{% endcomment %} +{% load i18n filer_admin_tags %}{% spaceless %} + +{% if object %} + + {{ object.label }} + +{% else %} + +{% endif %} + + + {% if search_label %} + + {{ search_label }} + {% else %} + {% trans 'Lookup' %} + {% endif %} + +{% if remove_label %} + +{% else %} + +{% endif %} +
      +{{ hidden_input }} + +{% endspaceless %} diff --git a/filer/templates/admin/filer/widgets/admin_folder.html b/filer/templates/admin/filer/widgets/admin_folder.html index 639c67139..836da2c60 100644 --- a/filer/templates/admin/filer/widgets/admin_folder.html +++ b/filer/templates/admin/filer/widgets/admin_folder.html @@ -1,26 +1,24 @@ -{% load i18n filer_admin_tags %}{% spaceless %} -{% if object %} - {% trans 'Folder' %}: {{ object.pretty_logical_path }} -{% else %} - {% trans 'Folder' %}: {% trans 'none selected' %} -{% endif %} - - {% trans 'Lookup' %} - - -
      -{{ hidden_input }} - +{% load i18n filer_admin_tags static %} + +{% spaceless %} +
      + + +   + {% trans "Choose Folder" %} + + + + + {% if object %} + {{ object.pretty_logical_path }} + {% endif %} + + + + + + + +
      {% endspaceless %} diff --git a/filer/templates/image_filer/image_export_form.html b/filer/templates/image_filer/image_export_form.html index 9f00dda26..381ab7f46 100644 --- a/filer/templates/image_filer/image_export_form.html +++ b/filer/templates/image_filer/image_export_form.html @@ -1,20 +1,24 @@ {% extends "admin/image_filer/image/change_form.html" %} {% trans i18n %} -{% load url from future %} {% block breadcrumbs %} {% endblock %} diff --git a/filer/templatetags/filer_admin_tags.py b/filer/templatetags/filer_admin_tags.py index 50cfa8d25..c62b5c906 100644 --- a/filer/templatetags/filer_admin_tags.py +++ b/filer/templatetags/filer_admin_tags.py @@ -1,10 +1,33 @@ -import django -from django.conf import settings +from math import ceil + +from django.contrib.staticfiles.storage import staticfiles_storage +from django.core.files.storage import FileSystemStorage from django.template import Library -from distutils.version import LooseVersion +from django.templatetags.static import static +from django.urls import reverse +from django.utils.html import escapejs, format_html_join +from django.utils.safestring import mark_safe +from django.utils.translation import gettext_lazy as _ + +from easy_thumbnails.engine import NoSourceGenerator +from easy_thumbnails.exceptions import InvalidImageFormatError +from easy_thumbnails.files import get_thumbnailer +from easy_thumbnails.options import ThumbnailOptions + +from filer import settings +from filer.admin.tools import admin_url_params, admin_url_params_encoded +from filer.models.imagemodels import BaseImage +from filer.settings import ( + DEFERRED_THUMBNAIL_SIZES, FILER_MAX_SVG_THUMBNAIL_SIZE, FILER_TABLE_ICON_SIZE, FILER_THUMBNAIL_ICON_SIZE, +) +import filer.models + register = Library() +assignment_tag = getattr(register, 'assignment_tag', register.simple_tag) + + def filer_actions(context): """ Track the number of times the action field has been rendered on the page, @@ -12,28 +35,230 @@ def filer_actions(context): """ context['action_index'] = context.get('action_index', -1) + 1 return context -filer_actions = register.inclusion_tag("admin/filer/actions.html", takes_context=True)(filer_actions) -# Shamelessly taken from django-cms -# This will go away when django < 1.4 compatibility will be dropped -if LooseVersion(django.get_version()) < LooseVersion('1.4'): - ADMIN_ICON_BASE = "%sadmin/img/admin/" % settings.STATIC_URL - ADMIN_CSS_BASE = "%sadmin/css/" % settings.STATIC_URL - ADMIN_JS_BASE = "%sadmin/js/" % settings.STATIC_URL -else: - ADMIN_ICON_BASE = "%sadmin/img/" % settings.STATIC_URL - ADMIN_CSS_BASE = "%sadmin/css/" % settings.STATIC_URL - ADMIN_JS_BASE = "%sadmin/js/" % settings.STATIC_URL +filer_actions = register.inclusion_tag( + "admin/filer/actions.html", takes_context=True)(filer_actions) + + +@register.inclusion_tag( + 'admin/filer/folder/list_type_switcher.html', + takes_context=True, +) +def filer_folder_list_type_switcher(context): + choice_list = settings.FILER_FOLDER_ADMIN_LIST_TYPE_CHOICES + current_list_type = context['list_type'] + # This solution is user-friendly when there's only 2 choices + # If there will be more list types then please change this switcher to more + # proper widget (like for e.g. select list) + next_list_type = next( + iter(choice_list[choice_list.index(current_list_type) + 1:]), + choice_list[0], + ) + + context['url'] = admin_url_params_encoded( + context['request'], + params={'_list_type': next_list_type}, + ) + context['tooltip_text'] = settings.FILER_FOLDER_ADMIN_LIST_TYPE_SWITCHER_SETTINGS[next_list_type]['tooltip_text'] + context['icon'] = settings.FILER_FOLDER_ADMIN_LIST_TYPE_SWITCHER_SETTINGS[next_list_type]['icon'] + return context + + +@register.simple_tag(takes_context=True) +def filer_admin_context_url_params(context, first_separator='?'): + return admin_url_params_encoded( + context['request'], first_separator=first_separator) + + +@register.simple_tag(takes_context=True) +def filer_admin_context_hidden_formfields(context): + request = context.get('request') + return format_html_join( + '\n', + '', + admin_url_params(request).items(), + ) + + +@assignment_tag(takes_context=True) +def filer_has_permission(context, item, action): + """Does the current user (taken from the request in the context) have + permission to do the given action on the given item. + + """ + permission_method_name = f'has_{action}_permission' + permission_method = getattr(item, permission_method_name, None) + request = context.get('request') + + if not permission_method or not request: + return False + # Call the permission method. + # This amounts to calling `item.has_X_permission(request)` + return permission_method(request) + + +def file_icon_context(file, detail, width, height): + mime_maintype, mime_subtype = file.mime_maintype, file.mime_subtype + context = { + 'mime_maintype': mime_maintype, + 'mime_type': file.mime_type, + } + height, width, context = get_aspect_ratio_and_download_url(context, detail, file, height, width) + # returned context if icon is not available + not_available_context = { + 'icon_url': staticfiles_storage.url('filer/icons/file-missing.svg'), + 'alt_text': _("File is missing"), + 'width': width, + 'height': width, # The icon is a square + } + # Check if file exists for performance reasons (only on FileSystemStorage) + if file.file and isinstance(file.file.source_storage, FileSystemStorage) and not file.file.exists(): + return not_available_context + + add_styles = {} + if isinstance(file, BaseImage): + thumbnailer = get_thumbnailer(file) + + # SVG files may contain multiple vector graphics, and width and height are not available for them. If file does + # not have width or height just ignore the thumbnail icon. Otherwise, continue with the standard procedure. + if file.width == 0.0 or file.height == 0.0: + icon_url = staticfiles_storage.url('filer/icons/file-unknown.svg') + else: + if detail: + opts = {'size': (width, height), 'upscale': True} + else: + opts = {'size': (width, height), 'crop': True} + thumbnail_options = ThumbnailOptions(opts) + # Optimize directory listing: + if width == height and width in DEFERRED_THUMBNAIL_SIZES and hasattr(file, "thumbnail_name"): + # Get name of thumbnail from easy-thumbnail + configured_name = thumbnailer.get_thumbnail_name(thumbnail_options, transparent=file._transparent) + # If the name was annotated: Thumbnail exists and we can use it + if configured_name == file.thumbnail_name: + icon_url = file.file.thumbnail_storage.url(configured_name) + if mime_subtype != 'svg+xml' and file.thumbnailx2_name: + context['highres_url'] = file.file.thumbnail_storage.url(file.thumbnailx2_name) + elif mime_subtype == 'svg+xml': + if file.size < FILER_MAX_SVG_THUMBNAIL_SIZE: + icon_url = file.url + else: + # Only display a generic image icon + # Better solution: Render a bitmap thumbnail from SVG + icon_url = staticfiles_storage.url('filer/icons/file-picture.svg') + add_styles = { + "object-fit": "cover", # Mimic the behavior of the thumbnail + } + else: # Probably does not exist, defer creation + icon_url = reverse("admin:filer_file_fileicon", args=(file.pk, width)) + context['alt_text'] = file.default_alt_text + else: + # Try creating thumbnails / take existing ones + try: + icon_url = thumbnailer.get_thumbnail(thumbnail_options).url + context['alt_text'] = file.default_alt_text + if mime_subtype != 'svg+xml': + thumbnail_options['size'] = 2 * width, 2 * height + context['highres_url'] = thumbnailer.get_thumbnail(thumbnail_options).url + except (InvalidImageFormatError, NoSourceGenerator): + # This is caught by file.exists() for file storage systems + # For remote storage systems we catch the error to avoid second trip + # to the storage system + return not_available_context + elif mime_maintype in ['audio', 'font', 'video']: + icon_url = staticfiles_storage.url(f'filer/icons/file-{mime_maintype}.svg') + height = width # icon is a square + elif mime_maintype == 'application' and mime_subtype in ['zip', 'pdf']: + icon_url = staticfiles_storage.url(f'filer/icons/file-{mime_subtype}.svg') + height = width # icon is a square + else: + icon_url = staticfiles_storage.url('filer/icons/file-unknown.svg') + height = width # icon is a square + context.update(width=width, height=height, icon_url=icon_url) + if add_styles: + styles = "; ".join(f"{k}: {v}" for k, v in add_styles.items()) + context.update(add_styles=f'style="{styles}"') + return context + + +def get_aspect_ratio_and_download_url(context, detail, file, height, width): + # Get download_url and aspect ratio right for detail view + if detail: + context['download_url'] = file.url + if isinstance(file, BaseImage): + # only check for file width, if the file + # is actually an image and not on other files + # because they don't really have width or height + if file.width: + width, height = 210, ceil(210 / file.width * file.height) + context['sidebar_image_ratio'] = '%.6f' % (file.width / 210) + return height, width, context + + +@register.inclusion_tag('admin/filer/templatetags/file_icon.html') +def file_icon(file, detail=False, size=None): + """ + This templatetag returns a rendered ` + to be used for rendering thumbnails of files in the directory listing or in the corresponding detail + views for that image. + """ + if size: + width, height = (int(s) for s in size.split('x')) + elif detail == "thumbnail": + width, height = FILER_THUMBNAIL_ICON_SIZE, FILER_THUMBNAIL_ICON_SIZE + elif detail is True: + width, height = 2 * FILER_TABLE_ICON_SIZE, 2 * FILER_TABLE_ICON_SIZE + else: + width, height = FILER_TABLE_ICON_SIZE, FILER_TABLE_ICON_SIZE + return file_icon_context(file, detail is True, width, height) -@register.simple_tag -def admin_icon_base(): - return ADMIN_ICON_BASE @register.simple_tag -def admin_css_base(): - return ADMIN_CSS_BASE +def file_icon_url(file): + # Cache since it is called repeatedly by templates + if not hasattr(file, "_file_icon_url_cache"): + context = file_icon_context(file, False, 2 * FILER_TABLE_ICON_SIZE, 2 * FILER_TABLE_ICON_SIZE) + file._file_icon_url_cache = escapejs(context.get('highres_url', context['icon_url'])) + return file._file_icon_url_cache + @register.simple_tag -def admin_js_base(): - return ADMIN_JS_BASE +def icon_css_library(): + html = "" + for lib in settings.ICON_CSS_LIB: + html += f'' + return mark_safe(html) + + +@register.simple_tag(takes_context=True) +def get_popup_params(context, sep='?'): + is_popup = context.get('is_popup', False) + select_folder = context.get('select_folder', False) + current_site = context.get('current_site', False) + file_type = context.get('file_type', None) + params = '' + if is_popup: + params += '%s_popup=1' % sep + if select_folder: + params += '&select_folder=1' + if current_site: + params += '¤t_site=%s' % current_site + if file_type: + params += '&file_type=%s' % file_type + return params + + +@register.filter +def pretty_display(filer_obj): + if isinstance(filer_obj, filer.models.Folder): + return '/%s' % '/'.join(filer_obj.get_ancestors(include_self=True) + .values_list('name', flat=True)) + if isinstance(filer_obj, filer.models.File): + name = filer_obj.actual_name + if not filer_obj.folder_id: + return '/%s' % name + return '/%s' % '/'.join( + list(filer.models.Folder.all_objects.get(id=filer_obj.folder_id) + .get_ancestors(include_self=True) + .values_list('name', flat=True)) + [name]) + return '' diff --git a/filer/templatetags/filer_image_tags.py b/filer/templatetags/filer_image_tags.py index bc0eb36bf..5588521f1 100644 --- a/filer/templatetags/filer_image_tags.py +++ b/filer/templatetags/filer_image_tags.py @@ -1,12 +1,17 @@ -#-*- coding: utf-8 -*- -from django.template import Library import re +from django.template import Library + + register = Library() RE_SIZE = re.compile(r'(\d+)x(\d+)$') +def percentage(part, whole): + return 100 * float(part) / float(whole) + + def _recalculate_size(size, index, divisor=0, padding=0, keep_aspect_ratio=False): new_one = size[index] @@ -15,8 +20,8 @@ def _recalculate_size(size, index, divisor=0, padding=0, if padding: new_one = new_one - padding if keep_aspect_ratio: - new_two = int(float(new_one) * \ - float(size[int(not index)]) / size[index]) + new_two = int( + float(new_one) * float(size[int(not index)]) / size[index]) else: new_two = int(size[int(not index)]) @@ -28,7 +33,7 @@ def _recalculate_size(size, index, divisor=0, padding=0, def _resize(original_size, index, divisor=0, padding=0, keep_aspect_ratio=False): - if isinstance(original_size, basestring): + if isinstance(original_size, str): m = RE_SIZE.match(original_size) if m: original_size = (int(m.group(1)), int(m.group(2))) @@ -56,6 +61,8 @@ def extra_padding_x(original_size, padding): Reduce the width of `original_size` by `padding` """ return _resize(original_size, 0, padding=padding) + + extra_padding_x = register.filter(extra_padding_x) @@ -65,6 +72,8 @@ def extra_padding_x_keep_ratio(original_size, padding): ratio. """ return _resize(original_size, 0, padding=padding, keep_aspect_ratio=True) + + extra_padding_x_keep_ratio = register.filter(extra_padding_x_keep_ratio) @@ -73,6 +82,8 @@ def extra_padding_y(original_size, padding): Reduce the height of `original_size` by `padding` """ return _resize(original_size, 1, padding=padding) + + extra_padding_y = register.filter(extra_padding_y) @@ -82,16 +93,22 @@ def extra_padding_y_keep_ratio(original_size, padding): ratio. """ return _resize(original_size, 1, padding=padding, keep_aspect_ratio=True) + + extra_padding_y_keep_ratio = register.filter(extra_padding_y_keep_ratio) def divide_x_by(original_size, divisor): return _resize(original_size, 0, divisor=divisor) + + devide_x_by = register.filter(divide_x_by) def divide_y_by(original_size, divisor): return _resize(original_size, 1, divisor=divisor) + + devide_y_by = register.filter(divide_y_by) @@ -99,4 +116,24 @@ def divide_xy_by(original_size, divisor): size = divide_x_by(original_size, divisor=divisor) size = divide_y_by(size, divisor=divisor) return size + + divide_xy_by = register.filter(divide_xy_by) + + +def get_css_position(image): + if not image or not image.subject_location: + return '50% 50%' + + x, y = image.subject_location.split(',') + width = image.width + height = image.height + + coords = '{}% {}%'.format( + percentage(x, width), + percentage(y, height) + ) + return coords + + +get_css_position = register.filter(get_css_position) diff --git a/filer/templatetags/filer_tags.py b/filer/templatetags/filer_tags.py index c5b2b50b9..faaba6109 100644 --- a/filer/templatetags/filer_tags.py +++ b/filer/templatetags/filer_tags.py @@ -1,7 +1,8 @@ -#-*- coding: utf-8 -*- -from django.template import Library import math +from django.template import Library + + register = Library() # The templatetag below is copied from sorl.thumbnail @@ -49,9 +50,10 @@ def filesize(bytes, format='auto1024'): elif format not in ('auto1024', 'auto1000', 'auto1024long', 'auto1000long'): return bytes + # Check for valid bytes try: - bytes = long(bytes) + bytes = int(bytes) except (ValueError, TypeError): return bytes @@ -82,12 +84,12 @@ def filesize(bytes, format='auto1024'): unit = filesize_long_formats.get(unit, '') if base == 1024 and unit: unit = '%sbi' % unit[:2] - unit = '%sbyte%s' % (unit, bytes != '1' and 's' or '') + unit = '{}byte{}'.format(unit, bytes != '1' and 's' or '') else: - unit = '%s%s' % (base == 1024 and unit.upper() or unit, + unit = '{}{}'.format(base == 1024 and unit.upper() or unit, base == 1024 and 'iB' or 'B') - return '%s %s' % (bytes, unit) + return f'{bytes} {unit}' if bytes == 0: return bytes @@ -99,4 +101,6 @@ def filesize(bytes, format='auto1024'): elif format_len == 3: bytes = bytes >> (10 * (base - 1)) return bytes / 1024.0 + + register.filter(filesize) diff --git a/filer/templatetags/filermedia.py b/filer/templatetags/filermedia.py index 84a7f60f7..92f86360a 100644 --- a/filer/templatetags/filermedia.py +++ b/filer/templatetags/filermedia.py @@ -4,6 +4,7 @@ register = Library() +@register.simple_tag def filer_staticmedia_prefix(): """ Returns the string contained in the setting FILER_STATICMEDIA_PREFIX. @@ -13,4 +14,4 @@ def filer_staticmedia_prefix(): except ImportError: return '' return settings.FILER_STATICMEDIA_PREFIX -filer_staticmedia_prefix = register.simple_tag(filer_staticmedia_prefix) + diff --git a/filer/test_settings.py b/filer/test_settings.py new file mode 100644 index 000000000..6d7bfcd19 --- /dev/null +++ b/filer/test_settings.py @@ -0,0 +1,121 @@ +# -*- coding: utf-8 -*- +import importlib.util +import os + +import filer + + +DEBUG = True +PACKAGE_ROOT = os.path.abspath(os.path.join( + os.path.dirname(filer.__file__), '..')) +TMP_ROOT = os.path.abspath(os.path.join(PACKAGE_ROOT, 'tmp')) +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(TMP_ROOT, 'filer_test.sqlite3'), + }, +} +INSTALLED_APPS = [ + 'filer', + 'mptt', + 'easy_thumbnails', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sites', + 'django.contrib.admin', + 'django.contrib.sessions', + 'django.contrib.staticfiles', +] + +# Optional CMS-related apps – only add them when they are actually installed. +_optional_apps = ['cms', 'menus', 'sekizai', 'cmsroles'] +for _app in _optional_apps: + if importlib.util.find_spec(_app) is not None: + INSTALLED_APPS.append(_app) + +ROOT_URLCONF = 'filer.test_urls' +SITE_ID = 1 +MEDIA_ROOT = os.path.abspath(os.path.join(TMP_ROOT, 'media')) +MEDIA_URL = '/media/' +STATIC_URL = '/static/' +USE_TZ = False + +MIDDLEWARE = [ + 'django.middleware.cache.UpdateCacheMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', +] + +if importlib.util.find_spec('cms') is not None: + MIDDLEWARE.append('cms.middleware.user.CurrentUserMiddleware') + CMS_TEMPLATES = [('cms_mock_template.html', 'cms_mock_template.html')] + CMS_MODERATOR = True + CMS_PERMISSION = True + +if importlib.util.find_spec('sekizai') is not None: + SEKIZAI_IGNORE_VALIDATION = True + +CACHE_BACKEND = 'locmem:///' + +FILER_FILE_MODELS = ( + 'filer.Image', + 'filer.Archive', + 'filer.File', +) + +SECRET_KEY = 'secret' +TEST_RUNNER = 'django.test.runner.DiscoverRunner' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'OPTIONS': { + 'context_processors': [ + "django.contrib.auth.context_processors.auth", + 'django.contrib.messages.context_processors.messages', + "django.template.context_processors.i18n", + "django.template.context_processors.debug", + "django.template.context_processors.request", + "django.template.context_processors.media", + 'django.template.context_processors.csrf', + "django.template.context_processors.static", + ], + 'loaders': ( + 'filer.tests.utils.MockLoader', + 'django.template.loaders.filesystem.Loader', + 'django.template.loaders.app_directories.Loader', + ), + 'debug': False + }, + }, +] + +# Append optional CMS/sekizai context processors when available. +_ctx = TEMPLATES[0]['OPTIONS']['context_processors'] +if importlib.util.find_spec('cms') is not None: + _ctx.append("cms.context_processors.media") +if importlib.util.find_spec('sekizai') is not None: + _ctx.append("sekizai.context_processors.sekizai") + +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'formatters': { + 'simple': { + 'format': '%(levelname)s %(module)s %(message)s' + }, + }, + 'handlers': { + 'console': { + 'class': 'logging.StreamHandler', + 'formatter': 'simple' + }, + }, + 'root': { + 'handlers': ['console', ], + 'level': 'WARNING', + }, +} diff --git a/filer/test_urls.py b/filer/test_urls.py new file mode 100644 index 000000000..a11f1157d --- /dev/null +++ b/filer/test_urls.py @@ -0,0 +1,8 @@ +#-*- coding: utf-8 -*- +from django.urls import path, include +from django.contrib import admin + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include('filer.server.urls')) +] \ No newline at end of file diff --git a/filer/tests/__init__.py b/filer/tests/__init__.py index 42d2dbbc3..7ecb3397d 100644 --- a/filer/tests/__init__.py +++ b/filer/tests/__init__.py @@ -1,8 +1,6 @@ #-*- coding: utf-8 -*- from filer.tests.admin import * -from filer.tests.fields import * from filer.tests.models import * -from filer.tests.permissions import * from filer.tests.server_backends import * from filer.tests.tools import * -from filer.tests.utils import * +from filer.tests.test_utils import * diff --git a/filer/tests/admin.py b/filer/tests/admin.py index 8f1d91d9a..120e507e8 100644 --- a/filer/tests/admin.py +++ b/filer/tests/admin.py @@ -1,67 +1,187 @@ #-*- coding: utf-8 -*- import os +import unittest +import zipfile +import io +import json from django.test import TestCase -from django.core.urlresolvers import reverse -import django.core.files +from django.urls import reverse +from django.core.exceptions import ValidationError +from django.core import files as dj_files from django.contrib.admin import helpers - +from django.contrib.sites.models import Site +from django.contrib.auth.models import User, Group, Permission +from django.http import HttpRequest +from django.core.files import File as DjangoFile from filer.models.filemodels import File +from filer.models.archivemodels import Archive from filer.models.foldermodels import Folder from filer.models.imagemodels import Image from filer.models.clipboardmodels import Clipboard from filer.models.virtualitems import FolderRoot from filer.models import tools -from filer.tests.helpers import (create_superuser, create_folder_structure, - create_image) +from filer.tests.helpers import ( + get_user_message, create_superuser, create_folder_structure, + create_image, move_action, + get_dir_listing_url, + filer_obj_as_checkox, get_make_root_folder_url, enable_restriction, + SettingsOverride +) +from filer.utils.checktrees import TreeChecker +from filer import settings as filer_settings +from filer.utils.generate_filename import by_path +from filer.admin import ClipboardAdmin +import filer.utils.files + +try: + from cmsroles.models import Role + from cmsroles.tests.tests import HelpersMixin + from cmsroles.siteadmin import get_site_admin_required_permission + HAS_CMSROLES = True +except ImportError: + HAS_CMSROLES = False + HelpersMixin = object class FilerFolderAdminUrlsTests(TestCase): + def setUp(self): self.superuser = create_superuser() self.client.login(username='admin', password='secret') + def tearDown(self): self.client.logout() + def test_filer_app_index_get(self): response = self.client.get(reverse('admin:app_list', args=('filer',))) self.assertEqual(response.status_code, 200) def test_filer_make_root_folder_get(self): - response = self.client.get(reverse('admin:filer-directory_listing-make_root_folder')+"?_popup=1") + response = self.client.get(get_make_root_folder_url() + "?_popup=1") self.assertEqual(response.status_code, 200) def test_filer_make_root_folder_post(self): FOLDER_NAME = "root folder 1" self.assertEqual(Folder.objects.count(), 0) - response = self.client.post(reverse('admin:filer-directory_listing-make_root_folder'), - { - "name":FOLDER_NAME, - }) + data_to_post = { + "name": FOLDER_NAME, + } + response = self.client.post( + get_make_root_folder_url(), + data_to_post) + self.assertIn('Site is required', response.content.decode()) + + data_to_post['site'] = 1 + response = self.client.post( + get_make_root_folder_url(), + data_to_post) + self.assertEqual(Folder.objects.count(), 1) self.assertEqual(Folder.objects.all()[0].name, FOLDER_NAME) - #TODO: not sure why the status code is 200 - self.assertEqual(response.status_code, 200) + self.assertEqual(response.status_code, 302) def test_filer_directory_listing_root_empty_get(self): - response = self.client.post(reverse('admin:filer-directory_listing-root')) + response = self.client.get(get_dir_listing_url(None)) self.assertEqual(response.status_code, 200) def test_filer_directory_listing_root_get(self): create_folder_structure(depth=3, sibling=2, parent=None) - response = self.client.post(reverse('admin:filer-directory_listing-root')) + response = self.client.get(get_dir_listing_url(None)) self.assertEqual(response.status_code, 200) self.assertEqual(response.context['folder'].children.count(), 6) + def test_validate_no_duplcate_folders(self): + FOLDER_NAME = "root folder 1" + self.assertEqual(Folder.objects.count(), 0) + post_data = {"name": FOLDER_NAME, "_popup": 1} + response = self.client.post( + get_make_root_folder_url(), + post_data) + self.assertIn('Site is required', response.content.decode()) + post_data['site'] = 1 + response = self.client.post( + get_make_root_folder_url(), + post_data) + self.assertEqual(Folder.objects.count(), 1) + self.assertEqual(Folder.objects.all()[0].name, FOLDER_NAME) + # and create another one + post_data = {"name": FOLDER_NAME, "_popup": 1} + response = self.client.post( + get_make_root_folder_url(), + post_data) + # second folder didn't get created + self.assertEqual(Folder.objects.count(), 1) + self.assertIn('folder name is already in use', + response.content.decode()) + + def test_validate_no_duplicate_folders_on_rename(self): + self.assertEqual(Folder.objects.count(), 0) + post_data = {"name": "foo", "_popup": 1} + response = self.client.post( + get_make_root_folder_url(), + post_data) + self.assertIn('Site is required', response.content.decode()) + post_data['site'] = 1 + response = self.client.post( + get_make_root_folder_url(), + post_data) + + self.assertEqual(Folder.objects.count(), 1) + self.assertEqual(Folder.objects.all()[0].name, "foo") + # and create another one + post_data = {"name": "bar", "_popup": 1} + response = self.client.post( + get_make_root_folder_url(), + post_data) + self.assertIn('Site is required', response.content.decode()) + + post_data['site'] = 1 + response = self.client.post( + get_make_root_folder_url(), + post_data) + + self.assertEqual(Folder.objects.count(), 2) + bar = Folder.objects.get(name="bar") + response = self.client.post( + reverse('admin:filer_folder_change', args=(bar.pk,)), + {"name": "foo", "site": bar.site_id, "_popup": 1}) + self.assertIn('folder name is already in use', + response.content.decode()) + # refresh from db and validate that it's name didn't change + bar = Folder.objects.get(pk=bar.pk) + self.assertEqual(bar.name, "bar") + + def test_changelist_not_accessible(self): + response = self.client.get("/admin/filer/file", follow=True) + self.assertEqual(response.status_code, 403) + + def test_change_view_accessible(self): + file1 = File.objects.create() + response = self.client.get("/admin/filer/file/{}".format(file1.id), follow=True) + self.assertEqual(response.status_code, 200) + class FilerImageAdminUrlsTests(TestCase): + def setUp(self): self.superuser = create_superuser() self.client.login(username='admin', password='secret') + def test_changelist_not_accessible(self): + response = self.client.get("/admin/filer/image", follow=True) + self.assertEqual(response.status_code, 403) + + def test_change_view_accessible(self): + image1 = Image.objects.create() + response = self.client.get("/admin/filer/image/{}".format(image1.id), follow=True) + self.assertEqual(response.status_code, 200) + def tearDown(self): self.client.logout() class FilerClipboardAdminUrlsTests(TestCase): + def setUp(self): self.superuser = create_superuser() self.client.login(username='admin', password='secret') @@ -75,33 +195,116 @@ def tearDown(self): self.client.logout() os.remove(self.filename) for img in Image.objects.all(): - img.delete() + img.delete(to_trash=False) + + def test_filer_upload_image_no_extension(self): + img_name = 'image_name' + image = create_image() + image_path = os.path.join(os.path.dirname(__file__), 'image_name') + image.save(image_path, 'JPEG') + file_obj = dj_files.File(open(image_path, 'rb')) + self.assertEqual(Image.objects.count(), 0) + response = self.client.post( + reverse('admin:filer-ajax_upload'), { + 'Filename': img_name, + 'Filedata': file_obj, + 'jsessionid': self.client.session.session_key, }, + ) + self.assertEqual(Image.objects.count(), 1) + img_obj = Image.objects.all()[0] + self.assertEqual(img_obj.actual_name, + '{}_{}.jpg'.format(img_obj.sha1[:10], img_name)) + os.remove(image_path) def test_filer_upload_file(self, extra_headers={}): self.assertEqual(Image.objects.count(), 0) - file_obj = django.core.files.File(open(self.filename)) + file_obj = dj_files.File(open(self.filename, 'rb')) response = self.client.post( - reverse('admin:filer-ajax_upload'), - {'Filename': self.image_name, 'Filedata': file_obj, 'jsessionid': self.client.session.session_key,}, + reverse('admin:filer-ajax_upload'), { + 'Filename': self.image_name, + 'Filedata': file_obj, + 'jsessionid': self.client.session.session_key, }, **extra_headers ) self.assertEqual(Image.objects.count(), 1) - self.assertEqual(Image.objects.all()[0].original_filename, self.image_name) + self.assertEqual(Image.objects.all()[0].original_filename, + self.image_name) - def test_filer_ajax_upload_file(self): + def test_file_upload_no_duplicate_files(self, extra_headers={}): self.assertEqual(Image.objects.count(), 0) - file_obj = django.core.files.File(open(self.filename)) + file_obj = dj_files.File(open(self.filename, 'rb')) + response = self.client.post( + reverse('admin:filer-ajax_upload'), { + 'Filename': self.image_name, + 'Filedata': file_obj, + 'jsessionid': self.client.session.session_key, }, + **extra_headers + ) + self.assertEqual(Image.objects.count(), 1) + self.assertEqual(Image.objects.all()[0].original_filename, + self.image_name) + self.assertEqual(Clipboard.objects.count(), 1) + clip = Clipboard.objects.get(id=1) # there is(or should be) just one clipboard + self.assertEqual(clip.files.count(), 1) + # upload the same file again with a fresh file handle. + # The stale clipboard entry should be replaced, not rejected. + file_obj2 = dj_files.File(open(self.filename, 'rb')) response = self.client.post( - reverse('admin:filer-ajax_upload')+'?filename=%s' % self.image_name, + reverse('admin:filer-ajax_upload'), { + 'Filename': self.image_name, + 'Filedata': file_obj2, + 'jsessionid': self.client.session.session_key, }, + **extra_headers + ) + self.assertEqual(Image.objects.count(), 1) + self.assertNotIn('error', response.content.decode()) + self.assertEqual(clip.files.count(), 1) + + def test_filer_ajax_upload_file(self): + self.assertEqual(Image.objects.count(), 0) + file_obj = dj_files.File(open(self.filename, 'rb')) + response = self.client.post(reverse('admin:filer-ajax_upload') + + '?filename=%s' % self.image_name, data=file_obj.read(), content_type='application/octet-stream', **{'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'} ) self.assertEqual(Image.objects.count(), 1) - self.assertEqual(Image.objects.all()[0].original_filename, self.image_name) + self.assertEqual(Image.objects.all()[0].original_filename, + self.image_name) + + def test_filer_ajax_upload_long_filename(self): + # additional setup + # create an image with a long filename + long_image_name = 'test' * 26 + '.jpg' # length of 104 title + 4 extension + filename = os.path.join(os.path.dirname(__file__), long_image_name) + long_name_img = create_image() + long_name_img.save(filename, 'JPEG') + + # preconditions: before upload + self.assertEqual(Image.objects.count(), 0) + + # try to upload + file_obj = dj_files.File(open(filename, 'rb')) + response = self.client.post(reverse('admin:filer-ajax_upload') + + '?filename=%s' % long_image_name, + data=file_obj.read(), + content_type='application/octet-stream', + **{'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'} + ) + # upload succedes + self.assertEqual(Image.objects.count(), 1) + # but title is not the long one + self.assertTrue(Image.objects.first().original_filename != long_image_name) + # it is first 100 characters + self.assertTrue(Image.objects.first().original_filename == 'test' * 25 + '.jpg') + + # additional tear down + os.remove(filename) -class BulkOperationsMixin(object): +class BulkOperationsMixin(object): + def setUp(self): self.superuser = create_superuser() self.client.login(username='admin', password='secret') @@ -112,8 +315,10 @@ def setUp(self): self.img.save(self.filename, 'JPEG') self.create_src_and_dst_folders() self.folder = Folder.objects.create(name="root folder", parent=None) - self.sub_folder1 = Folder.objects.create(name="sub folder 1", parent=self.folder) - self.sub_folder2 = Folder.objects.create(name="sub folder 2", parent=self.folder) + self.sub_folder1 = Folder.objects.create( + name="sub folder 1", parent=self.folder) + self.sub_folder2 = Folder.objects.create( + name="sub folder 2", parent=self.folder) self.image_obj = self.create_image(self.src_folder) self.create_file(self.folder) self.create_file(self.folder) @@ -128,89 +333,120 @@ def tearDown(self): self.client.logout() os.remove(self.filename) for f in File.objects.all(): - f.delete() + f.delete(to_trash=False) for folder in Folder.objects.all(): - folder.delete() + folder.delete(to_trash=False) def create_src_and_dst_folders(self): - self.src_folder = Folder(name="Src", parent=None) + site = Site.objects.get(id=1) + self.src_folder = Folder(name="Src", parent=None, site=site) self.src_folder.save() - self.dst_folder = Folder(name="Dst", parent=None) + self.dst_folder = Folder(name="Dst", parent=None, site=site) self.dst_folder.save() def create_image(self, folder, filename=None): filename = filename or 'test_image.jpg' - file_obj = django.core.files.File(open(self.filename), name=filename) - image_obj = Image.objects.create(owner=self.superuser, original_filename=self.image_name, file=file_obj, folder=folder) + file_obj = dj_files.File(open(self.filename, 'rb'), name=filename) + image_obj = Image.objects.create( + owner=self.superuser, original_filename=self.image_name, + file=file_obj, folder=folder) image_obj.save() return image_obj def create_file(self, folder, filename=None): filename = filename or 'test_file.dat' - file_data = django.core.files.base.ContentFile('some data') - file_data.name = filename - file_obj = File.objects.create(owner=self.superuser, original_filename=filename, file=file_data, folder=folder) + file_data = dj_files.base.ContentFile(b'some data', name=filename) + file_obj = File.objects.create(owner=self.superuser, + original_filename=filename, file=file_data, folder=folder) file_obj.save() return file_obj +@SettingsOverride(filer_settings, + FILER_PUBLICMEDIA_UPLOAD_TO=by_path, FOLDER_AFFECTS_URL=True) class FilerBulkOperationsTests(BulkOperationsMixin, TestCase): + def test_move_files_and_folders_action(self): # TODO: Test recursive (files and folders tree) move self.assertEqual(self.src_folder.files.count(), 1) self.assertEqual(self.dst_folder.files.count(), 0) - url = reverse('admin:filer-directory_listing', kwargs={ - 'folder_id': self.src_folder.id, - }) - response = self.client.post(url, { - 'action': 'move_files_and_folders', - 'post': 'yes', - 'destination': self.dst_folder.id, - helpers.ACTION_CHECKBOX_NAME: 'file-%d' % (self.image_obj.id,), - }) + response, _ = move_action( + self.client, self.src_folder, self.dst_folder, [self.image_obj]) self.assertEqual(self.src_folder.files.count(), 0) self.assertEqual(self.dst_folder.files.count(), 1) - url = reverse('admin:filer-directory_listing', kwargs={ - 'folder_id': self.dst_folder.id, - }) - response = self.client.post(url, { - 'action': 'move_files_and_folders', - 'post': 'yes', - 'destination': self.src_folder.id, - helpers.ACTION_CHECKBOX_NAME: 'file-%d' % (self.image_obj.id,), - }) + + response, _ = move_action( + self.client, self.dst_folder, self.src_folder, [self.image_obj]) self.assertEqual(self.src_folder.files.count(), 1) self.assertEqual(self.dst_folder.files.count(), 0) - def test_move_to_clipboard_action(self): - # TODO: Test recursive (files and folders tree) move + def test_validate_no_duplicate_folders_on_move(self): + """ move file from foo to bar + foo + |--file + bar + |--file + """ + foo = Folder.objects.create(name='foo', site=Site.objects.get(id=1)) + bar = Folder.objects.create(name='bar', site=Site.objects.get(id=1)) + file_foo = File.objects.create( + original_filename='file', folder=foo, + file=dj_files.base.ContentFile(b'some data', name='data.bin')) + file_bar = File.objects.create( + original_filename='file', folder=bar, + file=dj_files.base.ContentFile(b'some data', name='data.bin')) + + response, url = move_action( + self.client, foo, bar, [file_foo], follow=True) + self.assertRedirects(response, url) + self.assertIn( + "already exist at the selected destination", + get_user_message(response).message) + + foo = Folder.objects.get(id=foo.id) + file_foo = File.objects.get(id=file_foo.id) + self.assertEqual(foo.files.count(), 1) + self.assertEqual(file_foo.parent.id, foo.id) + + bar = Folder.objects.get(id=bar.id) + file_bar = File.objects.get(id=file_bar.id) + self.assertEqual(bar.files.count(), 1) + self.assertEqual(file_bar.parent.id, bar.id) + + def test_validate_no_duplicate_folders_on_move(self): + """Create the following folder hierarchy: + root + | + |--foo + | |-bar + | + |--bar + + and try to move the owter bar in foo. This has to fail since it + would result in two folders with the same name and parent. + """ + root = Folder.objects.create(name='root', owner=self.superuser) + foo = Folder.objects.create( + name='foo', parent=root, owner=self.superuser) + bar = Folder.objects.create( + name='bar', parent=root, owner=self.superuser) + foos_bar = Folder.objects.create( + name='bar', parent=foo, owner=self.superuser) + url = get_dir_listing_url(root) + + response, _ = move_action(self.client, root, foo, [bar]) + # refresh from db and validate that it hasn't been moved + bar = Folder.objects.get(pk=bar.pk) + self.assertEqual(bar.parent.pk, root.pk) - self.assertEqual(self.src_folder.files.count(), 1) - self.assertEqual(self.dst_folder.files.count(), 0) - url = reverse('admin:filer-directory_listing', kwargs={ - 'folder_id': self.src_folder.id, - }) - response = self.client.post(url, { - 'action': 'move_to_clipboard', - helpers.ACTION_CHECKBOX_NAME: 'file-%d' % (self.image_obj.id,), - }) - self.assertEqual(self.src_folder.files.count(), 0) - self.assertEqual(self.dst_folder.files.count(), 0) - clipboard = Clipboard.objects.get(user=self.superuser) - self.assertEqual(clipboard.files.count(), 1) - tools.move_files_from_clipboard_to_folder(clipboard, self.src_folder) - tools.discard_clipboard(clipboard) - self.assertEqual(clipboard.files.count(), 0) - self.assertEqual(self.src_folder.files.count(), 1) def test_files_set_public_action(self): + return self.image_obj.is_public = False self.image_obj.save() self.assertEqual(self.image_obj.is_public, False) - url = reverse('admin:filer-directory_listing', kwargs={ - 'folder_id': self.src_folder.id, - }) + url = get_dir_listing_url(self.src_folder) response = self.client.post(url, { 'action': 'files_set_public', helpers.ACTION_CHECKBOX_NAME: 'file-%d' % (self.image_obj.id,), @@ -219,12 +455,11 @@ def test_files_set_public_action(self): self.assertEqual(self.image_obj.is_public, True) def test_files_set_private_action(self): + return self.image_obj.is_public = True self.image_obj.save() self.assertEqual(self.image_obj.is_public, True) - url = reverse('admin:filer-directory_listing', kwargs={ - 'folder_id': self.src_folder.id, - }) + url = get_dir_listing_url(self.src_folder) response = self.client.post(url, { 'action': 'files_set_private', helpers.ACTION_CHECKBOX_NAME: 'file-%d' % (self.image_obj.id,), @@ -240,9 +475,7 @@ def test_copy_files_and_folders_action(self): self.assertEqual(self.src_folder.files.count(), 1) self.assertEqual(self.dst_folder.files.count(), 0) self.assertEqual(self.image_obj.original_filename, 'test_file.jpg') - url = reverse('admin:filer-directory_listing', kwargs={ - 'folder_id': self.src_folder.id, - }) + url = get_dir_listing_url(self.src_folder) response = self.client.post(url, { 'action': 'copy_files_and_folders', 'post': 'yes', @@ -255,13 +488,40 @@ def test_copy_files_and_folders_action(self): self.assertEqual(self.src_folder.files[0].id, self.image_obj.id) dst_image_obj = self.dst_folder.files[0] self.assertEqual(dst_image_obj.original_filename, 'test_filetest.jpg') + self.assertTrue(os.path.exists( + File.objects.get(id=dst_image_obj.id).file.path)) + self.assertTrue(os.path.exists( + File.objects.get(id=self.image_obj.id).file.path)) + + def test_copy_recursion_error(self): + ## it's enough to try to move/copy to itself with no error + ## this means the operation error is caught + url = get_dir_listing_url(None) + response = self.client.post(url, { + 'action': 'copy_files_and_folders', + 'post': 'yes', + 'suffix': 'test', + 'destination': self.src_folder.id, + helpers.ACTION_CHECKBOX_NAME: + filer_obj_as_checkox(self.src_folder), + }) + response = self.client.post(url, { + 'action': 'move_files_and_folders', + 'post': 'yes', + 'destination': self.src_folder.id, + helpers.ACTION_CHECKBOX_NAME: + filer_obj_as_checkox(self.src_folder), + }, follow=True) + class FilerDeleteOperationTests(BulkOperationsMixin, TestCase): + def test_delete_files_or_folders_action(self): - self.assertNotEqual(File.objects.count(), 0) - self.assertNotEqual(Image.objects.count(), 0) - self.assertNotEqual(Folder.objects.count(), 0) - url = reverse('admin:filer-directory_listing-root') + file_count = File.objects.count() + folder_count = Folder.objects.count() + self.assertNotEqual(file_count, 0) + self.assertNotEqual(folder_count, 0) + url = get_dir_listing_url(None) folders = [] for folder in FolderRoot().children.all(): folders.append('folder-%d' % (folder.id,)) @@ -271,38 +531,45 @@ def test_delete_files_or_folders_action(self): helpers.ACTION_CHECKBOX_NAME: folders, }) self.assertEqual(File.objects.count(), 0) + self.assertEqual(File.trash.count(), file_count) self.assertEqual(Folder.objects.count(), 0) + self.assertEqual(Folder.trash.count(), folder_count) def test_delete_files_or_folders_action_with_mixed_types(self): - # add more files/images so we can test the polymorphic queryset with multiple types + # add more files/images so we can test the polymorphic queryset + # with multiple types self.create_file(folder=self.src_folder) self.create_image(folder=self.src_folder) self.create_file(folder=self.src_folder) + qs = File.objects.filter( + folder__in=[self.folder.id, self.sub_folder1.id]) + file_count = qs.count() - self.assertNotEqual(File.objects.count(), 0) - self.assertNotEqual(Image.objects.count(), 0) - url = reverse('admin:filer-directory_listing', args=(self.folder.id,)) - folders = [] + url = get_dir_listing_url(self.folder) + items_to_delete = [] for f in File.objects.filter(folder=self.folder): - folders.append('file-%d' % (f.id,)) - folders.append('folder-%d' % self.sub_folder1.id) + items_to_delete.append('file-%d' % (f.id,)) + items_to_delete.append('folder-%d' % self.sub_folder1.id) response = self.client.post(url, { 'action': 'delete_files_or_folders', 'post': 'yes', - helpers.ACTION_CHECKBOX_NAME: folders, + helpers.ACTION_CHECKBOX_NAME: items_to_delete, }) - self.assertEqual(File.objects.filter(folder__in=[self.folder.id, self.sub_folder1.id]).count(), 0) + + alive_files = qs.count() + self.assertEqual(alive_files, 0) + self.assertEqual(File.trash.count(), file_count - alive_files) class FilerResizeOperationTests(BulkOperationsMixin, TestCase): + def test_resize_images_action(self): # TODO: Test recursive (files and folders tree) processing - self.assertEqual(self.image_obj.width, 800) self.assertEqual(self.image_obj.height, 600) - url = reverse('admin:filer-directory_listing', kwargs={ - 'folder_id': self.src_folder.id, - }) + # since the 'resize' action is disabled from the admin + return + url = get_dir_listing_url(self.src_folder.id) response = self.client.post(url, { 'action': 'resize_images', 'post': 'yes', @@ -317,17 +584,2048 @@ def test_resize_images_action(self): self.assertEqual(self.image_obj.height, 42) -class PermissionAdminTest(TestCase): +class BaseTestFolderTypePermissionLayer(object): + + def test_default_add_view_is_forbidden(self): + response = self.client.get(reverse('admin:filer_folder_add')) + self.assertEqual(response.status_code, 403) + + def test_change_child_site_folder(self): + f1 = Folder.objects.create(name='foo', site=Site.objects.get(id=1)) + f2 = Folder.objects.create(name='foo_bar', parent=f1) + # regular users should be able to change child folders + response = self.client.get( + reverse('admin:filer_folder_change', args=(f2.pk, ))) + self.assertEqual(response.status_code, 200) + self.assertIn('adminform', response.context_data) + # make sure the folder that is going to be saved is a site folder + form = response.context_data['adminform'].form + self.assertEqual(form.instance.folder_type, Folder.SITE_FOLDER) + self.assertCountEqual(sorted(['name', 'restricted']), + sorted(form.fields.keys())) + # check if save worked + response = self.client.post( + reverse('admin:filer_folder_change', args=(f2.pk, )), { + 'name': 'foo_bar__changed' + }) + self.assertEqual(response.status_code, 302) + f2__changed = Folder.objects.get(id=f2.pk) + self.assertEqual(f2__changed.name, 'foo_bar__changed') + self.assertEqual(f2__changed.folder_type, Folder.SITE_FOLDER) + + def test_add_core_folder(self): + f1 = Folder.objects.create( + name='foo', folder_type=Folder.CORE_FOLDER) + f2 = Folder.objects.create( + name='foo_bar', parent=f1, folder_type=Folder.CORE_FOLDER) + self.assertEqual(f1.folder_type, Folder.CORE_FOLDER) + self.assertEqual(f2.folder_type, Folder.CORE_FOLDER) + url = get_make_root_folder_url() + response = self.client.get(url,{ + 'parent_id': f2.id + }) + self.assertEqual(response.status_code, 403) + + response = self.client.post(url,{ + 'parent_id': f2.id, + 'name': 'foo_bar_core' + }) + self.assertEqual(response.status_code, 403) + + def test_change_core_folder(self): + f1 = Folder.objects.create( + name='foo', folder_type=Folder.CORE_FOLDER) + f2 = Folder.objects.create( + name='foo_bar', parent=f1, folder_type=Folder.CORE_FOLDER) + self.assertEqual(f1.folder_type, Folder.CORE_FOLDER) + self.assertEqual(f2.folder_type, Folder.CORE_FOLDER) + # No one should be able to change core folders + response = self.client.post( + reverse('admin:filer_folder_change', args=(f2.pk, )), + {'post': ['yes']}) + self.assertEqual(response.status_code, 403) + response = self.client.post( + reverse('admin:filer_folder_change', args=(f1.pk, )), + {'post': ['yes']}) + self.assertEqual(response.status_code, 403) + + def test_delete_child_site_folder(self): + f1 = Folder.objects.create(name='foo', site=Site.objects.get(id=1)) + f2 = Folder.objects.create(name='bar', parent=f1) + f3 = Folder.objects.create(name='baz', parent=f1) + # regular users should be able to delete child site folders + response = self.client.post( + reverse('admin:filer_folder_delete', args=(f2.pk, )), + {'post': ['yes']}) + self.assertEqual(response.status_code, 302) + self.assertEqual(Folder.objects.filter(id=f2.id).count(), 0) + + response = self.client.post(get_dir_listing_url(f1), { + 'action': 'delete_files_or_folders', + 'post': 'yes', + helpers.ACTION_CHECKBOX_NAME: ['folder-%d' % f3.id], + }) + self.assertEqual(response.status_code, 302) + self.assertEqual(Folder.objects.filter(id=f3.id).count(), 0) + + def test_delete_child_core_folder(self): + f1 = Folder.objects.create(name='foo', folder_type=Folder.CORE_FOLDER) + f2 = Folder.objects.create(name='bar', parent=f1) + f3 = Folder.objects.create(name='bazbazbazbaz', parent=f1) + self.assertEqual(Folder.objects.get(id=f1.id).is_core(), True) + self.assertEqual(Folder.objects.get(id=f2.id).is_core(), True) + self.assertEqual(Folder.objects.get(id=f3.id).is_core(), True) + # regular users should not be able to delete child core folders + response = self.client.post( + reverse('admin:filer_folder_delete', args=(f2.pk, )), + {'post': ['yes']}) + self.assertEqual(Folder.objects.filter(id=f2.id).count(), 1) + + response = self.client.post(get_dir_listing_url(f1), { + 'action': 'delete_files_or_folders', + 'post': 'yes', + helpers.ACTION_CHECKBOX_NAME: filer_obj_as_checkox(f3), + }) + self.assertEqual(Folder.objects.filter(id=f3.id).count(), 1) + + def test_add_root_folder(self): + # superusers should be able to add only root site folders + response = self.client.get( + get_make_root_folder_url()) + self.assertEqual(response.status_code, 200) + self.assertIn('adminform', response.context_data) + # make sure the folder that is going to be saved is a site folder + form = response.context_data['adminform'].form + self.assertEqual(form.instance.folder_type, Folder.SITE_FOLDER) + # only fields 'site', 'name' should be visible + expected_fields = ['site', 'name'] + if self.user.is_superuser: + expected_fields.append('shared') + self.assertCountEqual(sorted(expected_fields), + sorted(form.fields.keys())) + + s1, _ = Site.objects.get_or_create( + name='foo_site', domain='foo-domain.com') + response = self.client.post( + get_make_root_folder_url(), + {'name': 'foo', 'site': s1.id}) + self.assertEqual(response.status_code, 302) + self.assertEqual(Folder.objects.count(), 1) + + def test_change_root_core_folder(self): + f1 = Folder.objects.create( + name='foo', folder_type=Folder.CORE_FOLDER) + response = self.client.get( + reverse('admin:filer_folder_change', args=(f1.pk, ))) + self.assertEqual(response.status_code, 403) + response = self.client.post( + reverse('admin:filer_folder_change', args=(f1.pk, )), {}) + self.assertEqual(response.status_code, 403) + + def test_change_root_site_folder(self): + f1 = Folder.objects.create( + name='foo', folder_type=Folder.SITE_FOLDER) + response = self.client.get( + reverse('admin:filer_folder_change', args=(f1.pk, ))) + self.assertEqual(response.status_code, 200) + response = self.client.post( + reverse('admin:filer_folder_change', args=(f1.pk, )), {}) + self.assertEqual(response.status_code, 200) + + def test_delete_root_core_folder(self): + f1 = Folder.objects.create( + name='foo', folder_type=Folder.CORE_FOLDER) + + response = self.client.post( + reverse('admin:filer_folder_delete', args=(f1.pk, )), + {'post': 'yes'}) + self.assertEqual(Folder.objects.filter(id=f1.id).count(), 1) + response = self.client.post( + get_dir_listing_url(None), { + 'action': 'delete_files_or_folders', + 'post': 'yes', + helpers.ACTION_CHECKBOX_NAME: ['folder-%d' % f1.id], + }) + self.assertEqual(Folder.objects.filter(id=f1.id).count(), 1) + + def test_delete_root_site_folder(self): + f1 = Folder.objects.create( + name='foo', folder_type=Folder.SITE_FOLDER, + site=Site.objects.get(id=1)) + response = self.client.post( + reverse('admin:filer_folder_delete', args=(f1.pk, )), + {'post': 'yes'}) + self.assertEqual(Folder.objects.filter(id=f1.id).count(), 0) + f1 = Folder.objects.create( + name='foo', folder_type=Folder.SITE_FOLDER, + site=Site.objects.get(id=1)) + response = self.client.post( + get_dir_listing_url(None), { + 'action': 'delete_files_or_folders', + 'post': 'yes', + helpers.ACTION_CHECKBOX_NAME: ['folder-%d' % f1.id], + }) + self.assertEqual(Folder.objects.filter(id=f1.id).count(), 0) + + def _build_some_folder_structure(self, folder_type, site): + _folders, _files = {}, {} + foo1 = Folder.objects.create( + name='foo1', folder_type=folder_type, site=site) + _folders['foo1'] = foo1 + foo2 = Folder.objects.create( + name='foo2', folder_type=folder_type, site=site) + _folders['foo2'] = foo2 + bar = Folder.objects.create( + name='bar', folder_type=folder_type, parent=foo1, site=site) + _folders['bar'] = bar + baz1 = Folder.objects.create( + name='baz1', folder_type=folder_type, parent=bar, site=site) + _folders['baz1'] = baz1 + baz2 = Folder.objects.create( + name='baz2', folder_type=folder_type, parent=bar, site=site) + _folders['baz2'] = baz2 + + file_bar = File.objects.create( + original_filename='bar_file', folder=bar, + file=dj_files.base.ContentFile(b'some data', name='data.bin')) + _files['file_bar'] = file_bar + return _folders, _files + + def test_move_core_folders(self): + folders, files = self._build_some_folder_structure( + Folder.CORE_FOLDER, None) + + response, _ = move_action( + self.client, folders['bar'], folders['foo2'], [folders['baz1']]) + assert Folder.objects.filter(parent=folders['foo2']).count() == 0 + + def test_move_site_folder_to_core_destination_folder(self): + folders, files = self._build_some_folder_structure( + Folder.SITE_FOLDER, Site.objects.get(id=1)) + f1 = Folder.objects.create( + name='destination', folder_type=Folder.CORE_FOLDER) + response, _ = move_action( + self.client, folders['bar'], f1, [folders['baz1']]) + assert Folder.objects.filter(parent=f1).count() == 0 + f1.delete(to_trash=False) + + + def test_message_error_move_root_folder(self): + site = Site.objects.get(id=1) + foo = Folder.objects.create(name='foo', site=site) + bar = Folder.objects.create(name='bar', site=site) + response, url = move_action( + self.client, None, foo, [bar], follow=True) + if self.user.is_superuser: + self.assertIn( + "not allowed to move root folders", + get_user_message(response).message) + else: + self.assertIn( + "No action selected.", + get_user_message(response).message) + + def test_message_error_user_no_site_on_move(self): + site = Site.objects.get(id=1) + foo_root = Folder.objects.create(name='foo_root') + foo = Folder.objects.create(name='foo', parent=foo_root) + bar = Folder.objects.create(name='bar', site=site) + response, url = move_action( + self.client, foo_root, bar, [foo], follow=True) + self.assertRedirects(response, url) + self.assertIn( + "Some of the selected files/folders do not belong to any site.", + get_user_message(response).message) + + def test_message_error_user_sites_mismatch_on_move(self): + site = Site.objects.get(id=1) + other_site, _ = Site.objects.get_or_create( + name='foo_site', domain='foo-domain.com') + # make a root for foo in order to work for regular users + foo_root = Folder.objects.create(name='foo_root', site=other_site) + foo = Folder.objects.create(name='foo', parent=foo_root) + bar = Folder.objects.create(name='bar11', site=site) + url = get_dir_listing_url(foo_root) + response, url = move_action( + self.client, foo_root, bar, [foo], follow=True) + self.assertRedirects(response, url) + self.assertIn( + "Selected files/folders need to belong to the same site as the " + "destination folder.", + get_user_message(response).message) + + def test_destination_no_site_on_move(self): + site = Site.objects.get(id=1) + foo = Folder.objects.create(name='foo') + bar = Folder.objects.create(name='bar', site=site) + baz = Folder.objects.create(name='baz', site=site, parent=bar) + response, url = move_action(self.client, bar, foo, [baz]) + assert Folder.objects.filter(parent=foo.id).count() == 0 + + def test_folder_destination_filtering(self): + orphaned = Folder.objects.create(name='orphaned') + core = Folder.objects.create( + name='core', folder_type=Folder.CORE_FOLDER) + foo = Folder.objects.create( + name='foo', site=Site.objects.get(id=1)) + selected = Folder.objects.create( + parent=foo, name='selected', site=Site.objects.get(id=1)) + file_in_selected = File.objects.create( + folder=selected, original_filename='file_in_selected', + file=dj_files.base.ContentFile(b'some data', name='data.bin')) + valid_destination = Folder.objects.create( + parent=foo, name='valid', site=Site.objects.get(id=1)) + + def _fetch_destinations(parent): + url = reverse('admin:filer-destination_folders') + tree_data = json.loads( + self.client.get( + url, { + 'parent': parent, + 'selected_folders': json.dumps([selected.pk]), + 'current_folder': foo.pk + }, **{'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'} + ).content) + return {int(el['key']): el for el in tree_data} + + root_destinations = _fetch_destinations('null') + assert list(root_destinations.keys()) == [foo.id] + assert root_destinations[foo.id]['unselectable'] == True + foo_destinations = _fetch_destinations(foo.pk) + assert list(foo_destinations.keys()) == [valid_destination.id] + assert foo_destinations[valid_destination.id]['unselectable'] == False + + def test_move_from_unfiled(self): + foo_file = File.objects.create( + original_filename='foo_file', + file=dj_files.base.ContentFile(b'some data', name='data.bin')) + bar = Folder.objects.create( + name='bar', site=Site.objects.get(id=1)) + response, url = move_action(self.client, 'unfiled', bar, [foo_file]) + self.assertEqual(File.objects.filter(folder=bar).count(), 1) + self.assertEqual(File.objects.filter(folder__isnull=True).count(), 0) + + def test_copy_site_folder_to_core_destination_folder(self): + folders, files = self._build_some_folder_structure( + Folder.SITE_FOLDER, Site.objects.get(id=1)) + f1 = Folder.objects.create( + name='destination', folder_type=Folder.CORE_FOLDER) + + url = get_dir_listing_url(None) + response = self.client.post(url, { + 'action': 'copy_files_and_folders', + 'post': 'yes', + 'destination': f1.id, + helpers.ACTION_CHECKBOX_NAME: + [filer_obj_as_checkox(folders['bar'])]}, follow=True) + + messages = [str(m) for m in response.context['messages']] + assert any("The selected destination was not valid" in m for m in messages),\ + "Warning message not found in wrong copy response" + + def test_file_from_core_folder_is_unchangeable(self): + f1 = Folder.objects.create(name='foo', folder_type=Folder.CORE_FOLDER) + file1 = File.objects.create( + original_filename='bar_file', folder=f1, + file=dj_files.base.ContentFile(b'some data', name='data.bin')) + url = reverse('admin:filer_file_change', args=(file1.id, )) + response = self.client.get(url) + self.assertEqual(response.status_code, 200) + content = response.content.decode() + # No save button should be present (check for submit-row class + # used by Django admin for save buttons) + self.assertNotIn('submit-row', content) + self.assertNotIn('delete/', content) + # All form fields should be read-only (rendered as

      tags, not tags) + # The only elements should be csrfmiddlewaretoken (file form + logout form) + # plus the nav sidebar filter search input in Django 4.2+ + # Check that no editable form fields are present + self.assertNotIn('id="id_', content) + + def test_file_from_site_folder_is_changeable(self): + f1 = Folder.objects.create(name='foo', site=Site.objects.get(id=1)) + file1 = File.objects.create( + original_filename='bar_file', folder=f1, + file=dj_files.base.ContentFile(b'some data', name='data.bin')) + url = reverse('admin:filer_file_change', args=(file1.id, )) + response = self.client.get(url) + self.assertIn('submit-row', response.content.decode()) + self.assertIn('delete/', response.content.decode()) + # at least the choose file and csrfmiddlewaretoken + self.assertGreater(response.content.count(b' all descendants are restricted + * file restricted => keeps restriction from parent + even if set to unrestricted + """ + + def setUp(self): + username = 'login_using_foo' + password = 'secret' + user = User.objects.create_user(username=username, password=password) + user.is_superuser = user.is_staff = user.is_active = True + user.save() + self.client.login(username=username, password=password) + self.user = user + + def test_make_folder_restricted(self): + foo = Folder.objects.create(name='foo') + bar = Folder.objects.create(name='bar', parent=foo) + foo_file = File.objects.create( + original_filename='foo_file', folder=foo) + bar_file = File.objects.create( + original_filename='bar_file', folder=bar) + assert File.objects.filter(restricted=True).count() == 0 + assert Folder.objects.filter(restricted=True).count() == 0 + + foo.restricted = True + foo.save() + + assert File.objects.filter(restricted=False).count() == 0 + assert Folder.objects.filter(restricted=False).count() == 0 + + def test_cascade_change_on_parent_restriction(self): + s1 = Site.objects.get(id=1) + foo = Folder.objects.create(name='foo', site=s1) + foo_file = File.objects.create( + original_filename='foo_file', folder=foo) + bar = Folder.objects.create(name='bar', parent=foo) + bar_file = File.objects.create( + original_filename='bar_file', folder=bar) + baz = Folder.objects.create(name='baz', parent=bar) + bar.restricted = True + bar.save() + self.assertEqual(Folder.objects.get(id=foo.id).restricted, False) + self.assertEqual(File.objects.get(id=foo_file.id).restricted, False) + self.assertEqual(Folder.objects.get(id=bar.id).restricted, True) + self.assertEqual(File.objects.get(id=bar_file.id).restricted, True) + self.assertEqual(Folder.objects.get(id=baz.id).restricted, True) + self.assertEqual(Folder.objects.filter(site=s1).count(), 3) + response = self.client.post( + reverse('admin:filer_folder_change', args=(foo.pk, )), { + 'name': 'foo_only_name_changed', 'post': ['yes'], + 'restricted': False, + 'site': s1.id, + }) + self.assertEqual(response.status_code, 302) + self.assertEqual(Folder.objects.get(id=foo.id).restricted, False) + self.assertEqual(File.objects.get(id=foo_file.id).restricted, False) + self.assertEqual(Folder.objects.get(id=bar.id).restricted, True) + self.assertEqual(File.objects.get(id=bar_file.id).restricted, True) + self.assertEqual(Folder.objects.get(id=baz.id).restricted, True) + response = self.client.post( + reverse('admin:filer_folder_change', args=(foo.pk, )), { + 'name': 'foo', 'post': ['yes'], + 'restricted': True, + 'site': s1.id, + }) + self.assertEqual(response.status_code, 302) + self.assertEqual(Folder.objects.filter(restricted=True).count(), 3) + self.assertEqual(File.objects.filter(restricted=True).count(), 2) + + def test_make_file_restricted(self): + foo = Folder.objects.create(name='foo', restricted=True) + foo_file = File.objects.create( + original_filename='foo_file', folder=foo) + assert foo_file.restricted == True + + foo_file.restricted = False + foo_file.save() + + assert File.objects.get(pk=foo_file.pk).restricted == True + assert Folder.objects.get(pk=foo.pk).restricted == True + + +@unittest.skipUnless(HAS_CMSROLES, 'cmsroles not installed') +class TestFrozenAssetsPermissions(TestCase): + """ + Tests folder operations on frozen assets are restricted: + * add/move/copy/delete/extract in/from restricted folder + """ + + def _user_setup(self, user): + foo_base_group = Group.objects.create(name='foo_base_group') + developer_role = Role.objects.create( + name='foo_role', group=foo_base_group, + is_site_wide=True) + developer_role.grant_to_user(user, self.site) + + def setUp(self): + username = 'login_using_foo' + password = 'secret' + user = User.objects.create_user(username=username, password=password) + user.is_staff = user.is_active = True + user.save() + filer_perms = Permission.objects.filter( + content_type__app_label='filer').exclude( + codename='can_restrict_operations') + user.user_permissions.set(filer_perms) + self.site = Site.objects.get(id=1) + self._user_setup(user) + self.client.login(username=username, password=password) + self.user = user + # create file storage image + self.img = create_image() + self.image_name = 'foo_file.jpg' + self.filename = os.path.join( + os.path.dirname(__file__), self.image_name) + self.img.save(self.filename, 'JPEG') + # build filer files structure + self.folders, self.files = self._build_folder_structure() + + def _build_folder_structure(self): + foo = Folder.objects.create( + name='foo', site=self.site, restricted=True) + file_obj= DjangoFile(open(self.filename, 'rb'), name=self.image_name) + foo_file = Image.objects.create(original_filename=self.image_name, + file=file_obj, folder=foo) + foo_zippy = Archive.objects.create(original_filename='foo_file.zip', + file=dj_files.base.ContentFile(b'zippy', name='data.zip'), folder=foo) + assert foo.restricted == foo_file.restricted + return {'foo': foo}, {'foo_file': foo_file, 'foo_zippy': foo_zippy} + + def tearDown(self): + self.client.logout() + os.remove(self.filename) + + def test_make_subfolder_in_restricted(self): + post_data = { + "name": 'subfolder', "_popup": 1, + 'parent_id': self.folders['foo'].id} + response = self.client.post(get_make_root_folder_url(), post_data) + self.assertEqual(response.status_code, 403) + + def test_move_in_restricted(self): + bar = Folder.objects.create(name='bar', site=self.site) + bar_subfolder = Folder.objects.create( + name='bar1', site=self.site, parent=bar) + bar_file = File.objects.create( + original_filename='bar_file', + file=dj_files.base.ContentFile(b'some data', name='data.bin'), folder=bar) + response, _ = move_action( + self.client, bar, self.folders['foo'], [bar_file]) + self.assert_invalid_move_destination_response(response) + + response, _ = move_action( + self.client, bar, self.folders['foo'], [bar_subfolder]) + assert Folder.objects.filter(parent=self.folders['foo']).count() == 0 + bar_file.folder = None + bar_file.save() + response, _ = move_action( + self.client, 'unfiled', self.folders['foo'], [bar_file]) + assert File.objects.filter(folder=self.folders['foo']).count() == 2 + + + def assert_invalid_move_destination_response(self, response): + assert "The destination was not valid so the selected files and folders were "\ + "not moved. Please try again." in response.cookies['messages'].value,\ + "Was expecting error message because the destination is invalid" + assert response.status_code == 302 + + def test_move_restricted_in_dest(self): + bar = Folder.objects.create(name='bar', site=self.site) + foo_subfolder = Folder.objects.create( + name='foo_subfolder', site=self.site) + foo_subfolder.parent = self.folders['foo'] + foo_subfolder.save() + response, _ = move_action( + self.client, self.folders['foo'], bar, [foo_subfolder]) + self.assertEqual(File.objects.filter(folder=bar).count(), 0) + + response, _ = move_action( + self.client, self.folders['foo'], bar, [self.files['foo_file']]) + self.assertEqual(File.objects.filter(folder=bar).count(), 0) + + def test_extract_in_restricted(self): + self.assertEqual( + File.objects.filter(folder=self.folders['foo']).count(), 2) + url = get_dir_listing_url(self.folders['foo']) + response = self.client.post(url, { + 'action': 'extract_files', + helpers.ACTION_CHECKBOX_NAME: + [filer_obj_as_checkox(self.files['foo_zippy'])]}) + self.assertEqual( + File.objects.filter(folder=self.folders['foo']).count(), 2) + + def test_delete_from_restricted(self): + self.assertEqual( + File.objects.filter(id=self.files['foo_file'].id).count(), 1) + + url = get_dir_listing_url(self.folders['foo']) + response = self.client.post(url, { + 'action': 'delete_files_or_folders', + 'post': 'yes', + helpers.ACTION_CHECKBOX_NAME: + [filer_obj_as_checkox(self.files['foo_file'])], + }) + self.assertEqual( + File.objects.filter(id=self.files['foo_file'].id).count(), 1) + + url = get_dir_listing_url(None) + response = self.client.post(url, { + 'action': 'delete_files_or_folders', + 'post': 'yes', + helpers.ACTION_CHECKBOX_NAME: + [filer_obj_as_checkox(self.folders['foo'])], + }) + self.assertEqual( + File.objects.filter(id=self.files['foo_file'].id).count(), 1) + self.assertEqual( + Folder.objects.filter(id=self.folders['foo'].id).count(), 1) + + def test_delete_restricted(self): + bar = Folder.objects.create(name='bar', site=self.site) + bar_file = File.objects.create( + original_filename='bar_file', restricted=True, + file=dj_files.base.ContentFile(b'some data', name='data.bin'), folder=bar) + + url = get_dir_listing_url(bar) + response = self.client.post(url, { + 'action': 'delete_files_or_folders', + 'post': 'yes', + helpers.ACTION_CHECKBOX_NAME: + [filer_obj_as_checkox(bar_file)], + }) + self.assertEqual(response.status_code, 403) + + def test_copy_from_restricted(self): + bar = Folder.objects.create(name='bar', site=self.site) + url = get_dir_listing_url(self.folders['foo']) + response = self.client.post(url, { + 'action': 'copy_files_and_folders', + 'post': 'yes', + 'destination': bar.id, + helpers.ACTION_CHECKBOX_NAME: + [filer_obj_as_checkox(self.files['foo_file'])]}) + + assert File.objects.filter(folder=bar).count() == 1 + assert File.objects.get(folder=bar).restricted == False + + def test_copy_in_restricted(self): + bar = Folder.objects.create(name='bar', site=self.site) + bar_file = File.objects.create( + original_filename='bar_file', + file=dj_files.base.ContentFile(b'some data', name='data.bin'), folder=bar) + + url = get_dir_listing_url(bar) + response = self.client.post(url, { + 'action': 'copy_files_and_folders', + 'post': 'yes', + 'destination': self.folders['foo'].id, + helpers.ACTION_CHECKBOX_NAME: + [filer_obj_as_checkox(bar_file)]}) + self.assert_invalid_copy_destination_response(response) + + url = get_dir_listing_url(None) + response = self.client.post(url, { + 'action': 'copy_files_and_folders', + 'post': 'yes', + 'destination': self.folders['foo'].id, + helpers.ACTION_CHECKBOX_NAME: + [filer_obj_as_checkox(bar)]}) + self.assert_invalid_copy_destination_response(response) + + def assert_invalid_copy_destination_response(self, response): + assert "The selected destination was not valid, so the selected files and "\ + "folders were not copied. Please try again." in response.cookies['messages'].value,\ + "Was expecting error message because the destination is invalid" + assert response.status_code == 302 + + +@unittest.skipUnless(HAS_CMSROLES, 'cmsroles not installed') +class TestSharedSitePermissions(TestCase): + """ + Tests actions on shared folders + """ + def _user_setup(self, user): + filer_perms = Permission.objects.filter( + content_type__app_label='filer') + foo_base_group = Group.objects.create(name='foo_base_group') + foo_base_group.permissions.add(*filer_perms) + some_role = Role.objects.create( + name='foo_role', group=foo_base_group, + is_site_wide=True) + some_role.grant_to_user(user, self.site) + + def setUp(self): + username = 'login_using_foo' + password = 'secret' + user = User.objects.create_user(username=username, password=password) + user.is_staff = user.is_active = True + user.save() + self.site = Site.objects.get(id=1) + self.other_site = Site.objects.create( + domain='bar@example.com', name='BAR') + self._user_setup(user) + self.client.login(username=username, password=password) + self.user = user + self._create_folder_structure() + + def _create_folder_structure(self): + self.foo = Folder.objects.create(name='foo', site=self.site) + self.foo_child = Folder.objects.create(name='foo_child', + parent=self.foo) + self.bar = Folder.objects.create(name='bar', site=self.other_site) + self.bar_child = Folder.objects.create(name='bar_child', + parent=self.bar) + self.bar.shared.add(self.site) + assert self.foo_child.site.id == self.foo.site.id + assert self.bar_child.site.id == self.bar.site.id + + def get_listed_objects(self, folder, data={}): + response = self.client.get(get_dir_listing_url(folder), data) + try: + items = response.context['paginator'].object_list + except: + items = [] + return response, items + + def test_view_shared_folder(self): + bar_file = File.objects.create( + original_filename='bar_file.txt', folder=self.bar, + file=dj_files.base.ContentFile(b'file', name='file.bin')) + resp, items = self.get_listed_objects(None) + self.assertEqual(set([self.foo, self.bar]), set(items)) + resp, items = self.get_listed_objects(self.bar) + self.assertEqual(set([bar_file, self.bar_child]), set(items)) + bar_file.folder = self.bar_child + bar_file.save() + resp, items = self.get_listed_objects(self.bar_child) + self.assertEqual(set([bar_file]), set(items)) + + def test_add_in_shared_folder(self): + response = self.client.post( + get_make_root_folder_url(), + {'name': 'foo', 'parent_id': self.bar.id}) + self.assertEqual(response.status_code, 403) + + def test_change_shared_folder(self): + response = self.client.get( + reverse('admin:filer_folder_change', args=(self.bar.pk, ))) + self.assertEqual(response.status_code, 403) + response = self.client.get( + reverse('admin:filer_folder_change', args=(self.bar_child.pk, ))) + self.assertEqual(response.status_code, 403) + + def test_delete_shared_folder(self): + response = self.client.post( + reverse('admin:filer_folder_delete', args=(self.bar.pk, )), + {'post': 'yes'}) + self.assertEqual(response.status_code, 403) + response = self.client.post( + reverse('admin:filer_folder_delete', args=(self.bar_child.pk, )), + {'post': 'yes'}) + self.assertEqual(response.status_code, 403) + + url = get_dir_listing_url(None) + response = self.client.post(url, { + 'action': 'delete_files_or_folders', + 'post': 'yes', + helpers.ACTION_CHECKBOX_NAME: filer_obj_as_checkox(self.bar), + }) + self.assertEqual(Folder.objects.filter(id=self.bar.id).count(), 1) + self.assertEqual( + Folder.objects.filter(id=self.bar_child.id).count(), 1) + + url = get_dir_listing_url(self.bar) + response = self.client.post(url, { + 'action': 'delete_files_or_folders', + 'post': 'yes', + helpers.ACTION_CHECKBOX_NAME: filer_obj_as_checkox(self.bar_child), + }) + self.assertEqual(Folder.objects.filter(id=self.bar.id).count(), 1) + self.assertEqual( + Folder.objects.filter(id=self.bar_child.id).count(), 1) + + def test_move_from_shared_folder(self): + baz = Folder.objects.create(name='baz', site=self.other_site) + response, _ = move_action( + self.client, self.bar, baz, [self.bar_child]) + self.assertEqual(Folder.objects.get( + id=self.bar_child.id).parent.id, self.bar.id) + + def test_move_to_shared_folder(self): + unfiled_file = File.objects.create( + original_filename='bar_file.txt', + file=dj_files.base.ContentFile(b'file', name='file.bin')) + response, _ = move_action( + self.client, 'unfiled', self.bar, [unfiled_file]) + self.assertEqual(File.objects.get(id=unfiled_file.id).folder, None) + response, _ = move_action( + self.client, 'unfiled', self.bar_child, [unfiled_file]) + self.assertEqual(File.objects.get(id=unfiled_file.id).folder, None) + + def test_extract_files_shared_folder(self): + bar_zippy = Archive.objects.create( + original_filename='bar_zippy.zip', folder=self.bar, + file=dj_files.base.ContentFile(b'zippy', name='data.zip')) + assert Folder.objects.get(id=self.bar.id).files.count() == 1 + url = get_dir_listing_url(self.bar) + response = self.client.post(url, { + 'action': 'extract_files', + helpers.ACTION_CHECKBOX_NAME: + [filer_obj_as_checkox(bar_zippy)]}) + assert Folder.objects.get(id=self.bar.id).files.count() == 1 + +class TestSharedFolderFunctionality(TestCase): + """ + * only root folders can be shared + * shared sites changes are propagated for all descendants + """ + def setUp(self): + username = 'login_using_foo' + password = 'secret' + user = User.objects.create_user(username=username, password=password) + user.is_superuser = user.is_staff = user.is_active = True + user.save() + self.client.login(username=username, password=password) + self.user = user + + def test_changes_are_propagated_to_all_descendants(self): + site = Site.objects.get(id=1) + foo = Folder.objects.create(name='foo') + bar = Folder.objects.create(name='bar', parent=foo) + baz = Folder.objects.create(name='baz', parent=bar) + foo.shared.add(site) + for folder in Folder.objects.all(): + self.assertListEqual(list(folder.shared.all().order_by('domain')), + list(foo.shared.all().order_by('domain'))) + + def test_subfolder_inherits_from_parent(self): + s1 = Site.objects.create(name='foo', domain='foo.example.com') + data_to_post = { + "name": 'new_root', + "site": 1, + "shared": [1, s1.id], + } + response = self.client.post(get_make_root_folder_url(), data_to_post) + root = Folder.objects.get(name='new_root') + self.assertListEqual(list(root.shared.all().order_by('domain')), + list(Site.objects.all().order_by('domain'))) + data_to_post = { + "name": 'child', + "parent_id": root.id + } + response = self.client.post(get_make_root_folder_url(), data_to_post) + child = Folder.objects.get(name='child') + self.assertListEqual(list(child.shared.all().order_by('domain')), + list(root.shared.all().order_by('domain'))) + data_to_post = { + "name": 'child2', + "parent_id": child.id + } + response = self.client.post(get_make_root_folder_url(), data_to_post) + child2 = Folder.objects.get(name='child2') + self.assertListEqual(list(child2.shared.all().order_by('domain')), + list(child.shared.all().order_by('domain'))) + + def test_only_root_folders_can_be_shared(self): + foo = Folder.objects.create(name='foo') + bar = Folder.objects.create(name='bar', parent=foo) + response = self.client.get( + reverse('admin:filer_folder_change', args=(foo.pk, ))) + self.assertEqual(response.status_code, 200) + self.assertIn('adminform', response.context_data) + form = response.context_data['adminform'].form + self.assertCountEqual( + sorted(['name', 'restricted', 'shared', 'site']), + sorted(form.fields.keys())) + + response = self.client.get( + reverse('admin:filer_folder_change', args=(bar.pk, ))) + self.assertEqual(response.status_code, 200) + self.assertIn('adminform', response.context_data) + form = response.context_data['adminform'].form + self.assertCountEqual( + sorted(['name', 'restricted']), sorted(form.fields.keys())) + + def test_shared_sites_are_inherited_on_move(self): + s1 = Site.objects.create(name='s1', domain='s1.example.com') + s2 = Site.objects.create(name='s2', domain='s2.example.com') + site = Site.objects.get(id=1) + foo = Folder.objects.create(name='foo', site=site) + foo_1 = Folder.objects.create(name='foo1', parent=foo) + bar = Folder.objects.create(name='bar', site=site) + bar_1 = Folder.objects.create(name='bar1', parent=bar) + bar_12 = Folder.objects.create(name='bar12', parent=bar_1) + foo.shared.add(s1) + bar.shared.add(s2) + response, _ = move_action(self.client, bar, foo, [bar_1]) + foo_descendants = Folder.objects.get( + name='foo').get_descendants() + for desc_folder in [bar_1, bar_12]: + self.assertIn(desc_folder, foo_descendants) + self.assertCountEqual(desc_folder.shared.all(), [s1]) + + def test_shared_sites_are_inherited_on_copy(self): + s1 = Site.objects.create(name='s1', domain='s1.example.com') + s2 = Site.objects.create(name='s2', domain='s2.example.com') + site = Site.objects.get(id=1) + foo = Folder.objects.create(name='foo', site=site) + foo_1 = Folder.objects.create(name='foo1', parent=foo) + bar = Folder.objects.create(name='bar', site=site) + bar_1 = Folder.objects.create(name='bar1', parent=bar) + bar_12 = Folder.objects.create(name='bar12', parent=bar_1) + foo.shared.add(s1) + bar.shared.add(s2) + + response = self.client.post(get_dir_listing_url(bar), { + 'action': 'copy_files_and_folders', + 'post': 'yes', + 'suffix': '', + 'destination': foo.id, + helpers.ACTION_CHECKBOX_NAME: filer_obj_as_checkox(bar_1), + }, follow=True) + + bar_descendants = Folder.objects.get( + name='bar').get_descendants() + for desc_folder in [bar_1, bar_12]: + self.assertIn(desc_folder, bar_descendants) + self.assertCountEqual(desc_folder.shared.all(), [s2]) + + bar_1_copy = Folder.objects.get(name='bar1', parent=foo) + bar_12_copy = Folder.objects.get(name='bar12', parent=bar_1_copy) + foo_descendants = Folder.objects.get( + name='foo').get_descendants(include_self=True) + for desc_folder in [bar_1_copy, bar_12_copy, foo_1, foo]: + self.assertIn(desc_folder, foo_descendants) + self.assertCountEqual(desc_folder.shared.all(), [s1]) + foo.shared.remove(s1) + for desc_folder in [bar_1_copy, bar_12_copy, foo_1, foo]: + self.assertIn(desc_folder, foo_descendants) + self.assertCountEqual(desc_folder.shared.all(), []) + + +@unittest.skipUnless(HAS_CMSROLES, 'cmsroles not installed') +class TestAdminTools(TestCase): + """ + Tests for cases that are not covered by the tests above + """ + def _user_setup(self, user): + filer_perms = Permission.objects.filter( + content_type__app_label='filer').exclude( + codename='can_restrict_operations') + foo_base_group = Group.objects.create(name='foo_base_group') + foo_base_group.permissions.add(*filer_perms) + some_role = Role.objects.create( + name='foo_role', group=foo_base_group, + is_site_wide=True) + some_role.grant_to_user(user, self.site) + + def setUp(self): + username = 'login_using_foo' + password = 'secret' + user = User.objects.create_user(username=username, password=password) + user.is_staff = user.is_active = True + user.save() + self.site = Site.objects.get(id=1) + self.other_site = Site.objects.create( + domain='bar@example.com', name='BAR') + self._user_setup(user) + self.client.login(username=username, password=password) + self.user = user + + def test_valid_destination(self): + request = HttpRequest() + request.user = self.user + from filer.admin.tools import is_valid_destination + + foo = Folder.objects.create(name='foo') + # no site + self.assertEqual(is_valid_destination(request, foo), False) + foo.site = self.site + foo.save() + self.assertEqual(is_valid_destination(request, foo), True) + # restricted + foo.restricted = True + foo.save() + self.assertEqual(is_valid_destination(request, foo), False) + # core folder + foo.folder_type = Folder.CORE_FOLDER + foo.restricted = False + foo.save() + self.assertEqual(is_valid_destination(request, foo), False) + # other site's folder + bar = Folder.objects.create(name='bar', site=self.other_site) + self.assertEqual(is_valid_destination(request, bar), False) + self.user.is_superuser = True + self.user.save() + self.assertEqual(is_valid_destination(request, bar), True) + + def test_current_site_filtering(self): + request = HttpRequest() + request.GET = {} + request.GET['current_site'] = '1' + request.user = self.user + from filer.admin.tools import _filter_available_sites, files_available + self.assertCountEqual([1], _filter_available_sites('1', request.user)) + request.GET['current_site'] = 1 + self.assertCountEqual([1], _filter_available_sites('1', request.user)) + request.GET['current_site'] = 1 + self.assertCountEqual([1], _filter_available_sites('1', request.user)) + request.GET['current_site'] = '2' + self.assertEqual([], _filter_available_sites('2', request.user)) + f1 = File.objects.create(original_filename='foo_file') + request.GET['current_site'] = '1' + self.assertEqual( + len(files_available('1', request.user, File.objects.filter(id=f1.id))), 0) + + def test_multi_files_perms_for_restricted_descendants(self): + f1 = Folder.objects.create(name='1') + f2 = Folder.objects.create(name='2', parent=f1) + file2 = File.objects.create(original_filename='21', folder=f2) + f3 = Folder.objects.create(name='3', parent=f2) + file3 = File.objects.create(original_filename='31', folder=f3) + f1.site = self.other_site + f1.save() + + request = HttpRequest() + request.user = self.user + from filer.admin.tools import has_multi_file_action_permission + # test for folders from other site + self.assertEqual(has_multi_file_action_permission( + request, File.objects.none(), + Folder.objects.filter(id=f1.id)), False) + self.assertEqual(has_multi_file_action_permission( + request, File.objects.none(), + Folder.objects.filter(id=f2.id)), False) + self.assertEqual(has_multi_file_action_permission( + request, File.objects.none(), + Folder.objects.filter(id=f3.id)), False) + f1.site = self.site + f1.save() + # root folder and user is not site admin + self.assertEqual(has_multi_file_action_permission( + request, File.objects.none(), + Folder.objects.filter(id=f1.id)), False) + self.assertEqual(has_multi_file_action_permission( + request, File.objects.none(), + Folder.objects.filter(id=f2.id)), True) + self.assertEqual(has_multi_file_action_permission( + request, File.objects.none(), + Folder.objects.filter(id=f3.id)), True) + # level 1 file restriction + file2.restricted = True + file2.save() + self.assertEqual(has_multi_file_action_permission( + request, File.objects.none(), + Folder.objects.filter(id=f1.id)), False) + self.assertEqual(has_multi_file_action_permission( + request, File.objects.none(), + Folder.objects.filter(id=f2.id)), False) + self.assertEqual(has_multi_file_action_permission( + request, File.objects.none(), + Folder.objects.filter(id=f3.id)), True) + # level 1 folder restriction + file2.restricted = False + file2.save() + f2.restricted = True + f2.save() + self.assertEqual(has_multi_file_action_permission( + request, File.objects.none(), + Folder.objects.filter(id=f1.id)), False) + self.assertEqual(has_multi_file_action_permission( + request, File.objects.none(), + Folder.objects.filter(id=f2.id)), False) + self.assertEqual(has_multi_file_action_permission( + request, File.objects.none(), + Folder.objects.filter(id=f3.id)), False) + # level 2 folder restriction + f2.restricted = False + f2.save() + f3.restricted = True + f3.save() + self.assertEqual(has_multi_file_action_permission( + request, File.objects.none(), + Folder.objects.filter(id=f1.id)), False) + self.assertEqual(has_multi_file_action_permission( + request, File.objects.none(), + Folder.objects.filter(id=f2.id)), False) + self.assertEqual(has_multi_file_action_permission( + request, File.objects.none(), + Folder.objects.filter(id=f3.id)), False) + f1.restricted = True + f1.save() + self.assertEqual(File.objects.filter(restricted=False).count(), 0) + self.assertEqual(Folder.objects.filter(restricted=False).count(), 0) + + def test_truncate_filename_no_extension(self): + jpeg_file = io.BytesIO(b'\xff\xd8\xff\xe0\x00\x10JFIF') # jpeg signature + jpeg_file.name = '123456789' + filename = filer.utils.files.truncate_filename(jpeg_file, maxlen=7) + self.assertEqual(filename, '1234567.jpg') + + def test_truncate_filename_with_extension(self): + jpeg_file = io.BytesIO(b'\xff\xd8\xff\xe0\x00\x10JFIF') # jpeg signature + jpeg_file.name = '1234567.jpeg' + filename = filer.utils.files.truncate_filename(jpeg_file, maxlen=5) + self.assertEqual(filename, '12345.jpeg') + + +class TestTruncateFilename(TestCase): + """Tests for truncate_filename that don't require cmsroles.""" + + def test_truncate_filename_no_extension(self): + jpeg_file = io.BytesIO(b'\xff\xd8\xff\xe0\x00\x10JFIF') # jpeg signature + jpeg_file.name = '123456789' + filename = filer.utils.files.truncate_filename(jpeg_file, maxlen=7) + self.assertEqual(filename, '1234567.jpg') + + def test_truncate_filename_with_extension(self): + jpeg_file = io.BytesIO(b'\xff\xd8\xff\xe0\x00\x10JFIF') # jpeg signature + jpeg_file.name = '1234567.jpeg' + filename = filer.utils.files.truncate_filename(jpeg_file, maxlen=5) + self.assertEqual(filename, '12345.jpeg') + + +class TestMPTTCorruptionsOnFolderOperations(TestCase): + + def setUp(self): + self.site = Site.objects.get(id=1) + self.src_folder = Folder.objects.create(name='1', site=self.site) + self.dst_folder = Folder.objects.create(name='2', site=self.site) + username = 'login_using_foo' + password = 'secret' + user = User.objects.create_user(username=username, password=password) + user.is_superuser = user.is_staff = user.is_active = True + user.save() + self.client.login(username=username, password=password) + self.user = user + self.dirs, self.files = [], [] + + def test_move_operation(self): + create_folder_structure( + depth=2, sibling=2, + parent=Folder.objects.get(id=self.src_folder.id)) + # making sure no corruptions exist + TreeChecker().find_corruptions() + to_move = Folder.objects.filter( + parent__pk=self.src_folder.pk) + move_action(self.client, self.src_folder, self.dst_folder, to_move) + TreeChecker().find_corruptions() + + def test_copy_operation(self): + create_folder_structure( + depth=2, sibling=2, + parent=Folder.objects.get(id=self.src_folder.id)) + TreeChecker().find_corruptions() + to_copy = [ + filer_obj_as_checkox(child) + for child in Folder.objects.filter( + parent__pk=self.src_folder.pk)] + self.client.post(get_dir_listing_url(self.src_folder), { + 'action': 'copy_files_and_folders', + 'post': 'yes', + 'suffix': '', + 'destination': self.dst_folder.id, + helpers.ACTION_CHECKBOX_NAME: to_copy, + }) + TreeChecker().find_corruptions() + + def test_multi_folders_delete_operation(self): + create_folder_structure( + depth=2, sibling=2, + parent=Folder.objects.get(id=self.src_folder.id)) + TreeChecker().find_corruptions() + to_delete = [ + filer_obj_as_checkox(child) + for child in Folder.objects.filter( + parent__pk=self.src_folder.pk)] + response = self.client.post(get_dir_listing_url(self.src_folder), { + 'action': 'delete_files_or_folders', + 'post': 'yes', + helpers.ACTION_CHECKBOX_NAME: to_delete, + }) + TreeChecker().find_corruptions() + + def test_single_folder_delete_operation(self): + child_src_folder = Folder.objects.create( + name='1', parent=self.src_folder) + create_folder_structure( + depth=2, sibling=2, + parent=Folder.objects.get(id=child_src_folder.id)) + TreeChecker().find_corruptions() + delete_url = reverse( + 'admin:filer_folder_delete', args=(child_src_folder.pk, )) + response = self.client.post(delete_url, {'post': ['yes']}) + TreeChecker().find_corruptions() + + def tearDown(self): + for file_path in self.files: + os.remove(file_path) + for path in self.dirs: + os.removedirs(path) + + def test_extract_zip(self): + parent_path = os.path.dirname(__file__) + self.dirs = ['1/1', '1/2', '2/1'] + self.dirs = [os.path.join(parent_path, d) for d in self.dirs] + self.files = [] + for path in self.dirs: + os.makedirs(path) + file_path = os.path.join(path, 'name.txt') + with open(file_path, 'w') as fp: + fp.write('some data') + self.files.append(file_path) + + zip_file_path = os.path.join(parent_path, 'zip_file.zip') + zip_file = zipfile.ZipFile(zip_file_path, 'w') + for f in self.files: + arc_filename = f.replace(parent_path, '')[1:] + zip_file.write(f, arc_filename) + zip_file.close() + self.files.append(zip_file_path) + + filer_zipfile = Archive.objects.create( + original_filename='zip_file.zip', folder=self.src_folder, + file=dj_files.File(open(zip_file_path, 'rb'), name='zip_file.zip'), + ) + self.client.post(get_dir_listing_url(self.src_folder), { + 'action': 'extract_files', + helpers.ACTION_CHECKBOX_NAME: + [filer_obj_as_checkox(filer_zipfile)]}) + TreeChecker().find_corruptions() + + +class TestImageChangeForm(TestCase): + + def setUp(self): + self.user = create_superuser() self.client.login(username='admin', password='secret') def tearDown(self): self.client.logout() + for f in File.all_objects.all(): + f.delete(to_trash=False) + + def create_filer_image(self, image_name, **kwargs): + image = create_image() + image_path = os.path.join(os.path.dirname(__file__), image_name) + image.save(image_path, 'JPEG') + file_obj = DjangoFile(open(image_path, 'rb'), name=image_name) + kwargs.update({'original_filename': image_name, 'file': file_obj}) + image = Image.objects.create(**kwargs) + os.remove(image_path) + return image - def test_render_add_view(self): + def _create_another_PIL_image(self): + import PIL + size = (100, 50) + im = PIL.Image.new('RGB', size) + draw = PIL.ImageDraw.Draw(im) + red = (255, 0, 0) + text_pos = (10, 10) + text = "Hello World!" + draw.text(text_pos, text, fill=red) + del draw + return im + + def test_image_change_name_and_data(self): + with SettingsOverride(filer_settings, + FILER_PUBLICMEDIA_UPLOAD_TO=by_path, + FOLDER_AFFECTS_URL=True): + foo = Folder.objects.create(name='foo') + orig_img = self.create_filer_image( + 'one.jpg', folder=foo, owner=self.user) + sha1_before = orig_img.sha1 + self.assertEqual(orig_img.file.name, + 'foo/{}_one.jpg'.format(sha1_before[:10])) + + another_img_name = 'new_one.jpg' + another_img_path = os.path.join(os.path.dirname(__file__), + another_img_name) + pil_img = self._create_another_PIL_image() + pil_img.save(another_img_path, 'JPEG') + from django.core.files.uploadedfile import SimpleUploadedFile + with open(another_img_path, 'rb') as new_img: + img_url = reverse('admin:filer_image_change', + args=(orig_img.pk, )) + response = self.client.post(img_url, { + 'name': another_img_name, + 'file': SimpleUploadedFile(new_img.name, new_img.read()), + '_save': '', + }) + orig_img = File.objects.get(id=orig_img.id) + self.assertEqual(orig_img.file.name, + 'foo/{}_new_one.jpg'.format(orig_img.sha1[:10])) + self.assertNotEqual(sha1_before, orig_img.sha1) + os.remove(another_img_path) + + def test_image_change_name_only(self): + with SettingsOverride(filer_settings, + FILER_PUBLICMEDIA_UPLOAD_TO=by_path, + FOLDER_AFFECTS_URL=True): + foo = Folder.objects.create(name='foo') + orig_img = self.create_filer_image( + 'two.jpg', folder=foo, owner=self.user) + img_url = reverse('admin:filer_image_change', + args=(orig_img.pk, )) + response = self.client.post(img_url, { + 'name': 'new_two.jpg', + '_save': '', + }) + folder_url = reverse( + 'admin:filer-directory_listing', kwargs={'folder_id': foo.id}) + self.assertRedirects(response, folder_url) + orig_img = File.objects.get(id=orig_img.id) + self.assertEqual(orig_img.file.name, + 'foo/{}_new_two.jpg'.format(orig_img.sha1[:10])) + + def test_image_change_data_only(self): + with SettingsOverride(filer_settings, + FILER_PUBLICMEDIA_UPLOAD_TO=by_path, + FOLDER_AFFECTS_URL=True): + foo = Folder.objects.create(name='foo') + orig_img = self.create_filer_image( + 'three.jpg', folder=foo, owner=self.user) + sha1_before = orig_img.sha1 + another_img_name = 'new_three.jpg' + another_img_path = os.path.join(os.path.dirname(__file__), + another_img_name) + pil_img = self._create_another_PIL_image() + pil_img.save(another_img_path, 'JPEG') + from django.core.files.uploadedfile import SimpleUploadedFile + with open(another_img_path, 'rb') as new_img: + img_url = reverse('admin:filer_image_change', + args=(orig_img.pk, )) + response = self.client.post(img_url, { + 'file': SimpleUploadedFile(new_img.name, new_img.read()) + }) + orig_img = File.objects.get(id=orig_img.id) + self.assertNotEqual(sha1_before, orig_img.sha1) + os.remove(another_img_path) + + def test_image_change_name_in_popup(self): """ - Really stupid and simple test to see if the add Permission view can be rendered + Use case: open a popup, save image changes and then select the image """ - response = self.client.get(reverse('admin:filer_folderpermission_add')) - self.assertEqual(response.status_code, 200) \ No newline at end of file + with SettingsOverride(filer_settings, + FILER_PUBLICMEDIA_UPLOAD_TO=by_path, + FOLDER_AFFECTS_URL=True): + foo = Folder.objects.create(name='foo') + orig_img = self.create_filer_image( + 'four.jpg', folder=foo, owner=self.user) + img_url = reverse('admin:filer_image_change', args=(orig_img.pk, )) + response = self.client.post(img_url, { + 'name': 'new_four.jpg', + '_save': '', '_popup': '1', + }) + folder_url = "{}{}".format( + reverse('admin:filer-directory_listing', kwargs={'folder_id': foo.id}), + "?_popup=1") + self.assertRedirects(response, folder_url) + orig_img = File.objects.get(id=orig_img.id) + self.assertEqual(orig_img.file.name, + 'foo/{}_new_four.jpg'.format(orig_img.sha1[:10])) + + +class TrashAdminTests(TestCase): + + def setUp(self): + self.user = create_superuser() + self.client.login(username='admin', password='secret') + + def tearDown(self): + self.client.logout() + for f in File.all_objects.all(): + f.delete(to_trash=False) + + def create_filer_image(self, image_name, **kwargs): + image = create_image() + image_path = os.path.join(os.path.dirname(__file__), image_name) + image.save(image_path, 'JPEG') + file_obj = DjangoFile(open(image_path, 'rb'), name=image_name) + kwargs.update({ + 'original_filename': image_name, + 'file': file_obj + }) + image = Image.objects.create(**kwargs) + os.remove(image_path) + return image + + def test_restore_item_view(self): + img_dir = Folder.objects.create(name='dir') + img_dir_child = Folder.objects.create( + name='img_dir_child', parent=img_dir) + img = self.create_filer_image('to_be_deleted.jpg', folder=img_dir) + img_child = self.create_filer_image( + 'child_to_be_deleted.jpg', folder=img_dir_child) + Image.objects.get(id=img.id).delete() + Image.objects.get(id=img_child.id).delete() + Folder.objects.get(id=img_dir.id).delete() + + # search for child file + response = self.client.get(reverse('admin:filer_trash_changelist'), { + 'q': 'child_to_be_deleted'}) + items_displayed = response.context['paginator'].object_list + self.assertEqual(len(items_displayed), 1) + self.assertEqual(items_displayed[0].id, img_child.id) + + root_restore_url = reverse( + 'admin:filer_trash_item', args=('folder', img_dir.id,)) + for filer_model, filer_obj_id in [('file', img_child.id), ( + 'folder', img_dir_child.id)]: + restorable_item_url = reverse('admin:filer_trash_item', + args=(filer_model, filer_obj_id,)) + response = self.client.get(restorable_item_url) + self.assertEqual(response.status_code, 302) + self.assertTrue( + response.get('location').endswith(root_restore_url)) + restore_item_url = reverse('admin:filer_restore_items', + args=(filer_model, filer_obj_id,)) + response = self.client.post(restore_item_url, {'post': 'yes'}) + self.assertEqual(response.status_code, 403) + + +def get_listed_objects(client, folder, data={}): + response = client.get(get_dir_listing_url(folder), data) + try: + items = response.context['paginator'].object_list + except: + items = [] + return response, items + + +class TestImageFiltering(TestCase): + + def setUp(self): + username = 'login_using_foo' + password = 'secret' + user = User.objects.create_user(username=username, password=password) + user.is_staff = user.is_superuser = user.is_active = True + user.save() + self.client.login(username=username, password=password) + self.user = user + # create file storage image + self.img = create_image() + self.image_name = 'foo_file.jpg' + self.filename = os.path.join( + os.path.dirname(__file__), self.image_name) + self.img.save(self.filename, 'JPEG') + self.site = Site.objects.first() + self.foo = Folder.objects.create( + name='foo', site=self.site, restricted=True) + file_obj= DjangoFile(open(self.filename, 'rb'), name=self.image_name) + self.foo_image = Image.objects.create(original_filename=self.image_name, + file=file_obj, folder=self.foo) + self.foo_file = File.objects.create(original_filename=self.image_name, + file=file_obj, folder=self.foo) + + def test_get_images(self): + self.client.login(username='jack', password='secret') + _, items = get_listed_objects(self.client, self.foo, {'file_type': 'image'}) + assert {self.foo_image} == set(items) + _, items = get_listed_objects(self.client, self.foo) + assert {self.foo_image, self.foo_file} == set(items) diff --git a/filer/tests/commands.py b/filer/tests/commands.py new file mode 100644 index 000000000..d1d4f5a14 --- /dev/null +++ b/filer/tests/commands.py @@ -0,0 +1,107 @@ +""" Tests for management commdands. """ +from io import StringIO +from datetime import datetime, timedelta + +from django.test import TestCase +from django.core.management import call_command + +from filer.models.foldermodels import Folder +from filer.models.filemodels import File +from filer.settings import FILER_TRASH_CLEAN_INTERVAL + + +class TestTakeOutTrashCommand(TestCase): + """ Tests for the management command that clears the old items trash. """ + + def setUp(self): + # Regular files and folders + self.root_dir = Folder.objects.create(name='root_dir') + self.sub_dir = Folder.objects.create(name='sub_dir', parent=self.root_dir) + self.leaf_dir = Folder.objects.create(name='leaf_dir') + self.top_file = File.objects.create(original_filename="top_file") + self.middle_file = File.objects.create(original_filename="middle_file", folder=self.sub_dir) + self.bottom_file = File.objects.create(original_filename="bottom_file", folder=self.leaf_dir) + + self.now = datetime.now() + self.limit_time = self.now - timedelta(seconds=FILER_TRASH_CLEAN_INTERVAL) + self.long_ago = self.now - timedelta(days=1, seconds=FILER_TRASH_CLEAN_INTERVAL) + + # Recent trash (that can be restored) + self.recent_del_top_dir = Folder.objects.create( + name="recent_del_top_dir", deleted_at=self.limit_time + timedelta(days=1)) + self.recent_del_sub_dir = Folder.objects.create( + name="recent_del_sub_dir", parent=self.recent_del_top_dir, + deleted_at=self.limit_time + timedelta(hours=1)) + self.recent_del_empty_dir = Folder.objects.create(name="recent_del_empty_dir", + deleted_at=self.now) + self.recent_del_top_file = File.objects.create(original_filename="recent_del_top_file", + deleted_at=self.now) + self.recent_del_bottom_file = File.objects.create( + original_filename="recent_del_bottom_file", + deleted_at=self.limit_time + timedelta(days=2)) + + # Old trash (should be deleted) + self.old_del_dir = Folder.objects.create(name="old_del_dir", deleted_at=self.long_ago) + self.old_del_sub_dir = Folder.objects.create(name="old_del_sub_dir", + parent=self.old_del_dir, + deleted_at=self.long_ago) + self.old_del_empty_dir = Folder.objects.create(name="old_del_empty_dir", + deleted_at=self.long_ago) + self.old_del_top_file = File.objects.create(original_filename="old_del_top_file", + deleted_at=self.long_ago) + self.old_del_bottom_file = File.objects.create(original_filename="old_del_bottom_file", + deleted_at=self.long_ago) + + def test_trash_is_cleared(self): + stdout, stderr = self.run_trash_command() + self.assertEqual(stderr.getvalue(), "", "Errors found while running command!") + stdout_val = stdout.getvalue() + deleted_files = stdout_val.count("Deleting file") + self.assertEqual(deleted_files, 2, + "Deleted unexpected number of files: " + str(deleted_files)) + deleted_folders = stdout_val.count("Deleting folder") + self.assertEqual(deleted_folders, 3, + "Deleted unexpected number of folders: " + str(deleted_folders)) + self.assert_required_files_remain() + self.assert_folder_does_not_exist("old_del_dir") + self.assert_folder_does_not_exist("old_del_sub_dir") + self.assert_folder_does_not_exist("old_del_empty_dir") + self.assert_file_does_not_exist("old_del_top_file") + self.assert_file_does_not_exist("old_del_bottom_file") + + def test_no_operation(self): + File.trash.filter(deleted_at__lt=self.limit_time).delete() + Folder.trash.filter(deleted_at__lt=self.limit_time).delete() + stdout, stderr = self.run_trash_command() + self.assertEqual(stdout.getvalue(), "No old files or folders.\n") + self.assertEqual(stderr.getvalue(), "", "Errors found while running command!") + self.assert_required_files_remain() + + def run_trash_command(self): + stdout = StringIO() + stderr = StringIO() + call_command("take_out_filer_trash", stdout=stdout, stderr=stderr) + return stdout, stderr + + def assert_required_files_remain(self): + root_dir = Folder.objects.get(name="root_dir") + sub_dir = Folder.objects.get(name="sub_dir", parent=root_dir) + leaf_dir = Folder.objects.get(name="leaf_dir") + File.objects.get(original_filename="top_file") + File.objects.get(original_filename="middle_file", folder=sub_dir) + File.objects.get(original_filename="bottom_file", folder=leaf_dir) + + recent_del_top_dir = Folder.all_objects.get(name="recent_del_top_dir") + Folder.all_objects.get(name="recent_del_sub_dir", parent=recent_del_top_dir) + Folder.all_objects.create(name="recent_del_empty_dir") + File.all_objects.get(original_filename="recent_del_top_file") + File.all_objects.get(original_filename="recent_del_bottom_file") + + def assert_folder_does_not_exist(self, folder_name): + with self.assertRaises(Folder.DoesNotExist): + Folder.all_objects.get(name=folder_name) + + def assert_file_does_not_exist(self, file_name): + with self.assertRaises(File.DoesNotExist): + File.all_objects.get(original_filename=file_name) + diff --git a/filer/tests/fields.py b/filer/tests/fields.py deleted file mode 100644 index 1bf439d79..000000000 --- a/filer/tests/fields.py +++ /dev/null @@ -1,9 +0,0 @@ -# -*- coding: utf-8 -*- -from django.core.exceptions import ImproperlyConfigured -from django.test.testcases import TestCase -from filer.fields.image import FilerImageField - -class FieldsTests(TestCase): - def test_related_name_validation(self): - self.assertRaises(ImproperlyConfigured, FilerImageField, related_name='thumbnails') - FilerImageField(related_name='not_thumbnails') diff --git a/filer/tests/foo_file.jpg b/filer/tests/foo_file.jpg new file mode 100644 index 000000000..9e4936f71 Binary files /dev/null and b/filer/tests/foo_file.jpg differ diff --git a/filer/tests/helpers.py b/filer/tests/helpers.py index 1ce73dffe..d9f158bd7 100644 --- a/filer/tests/helpers.py +++ b/filer/tests/helpers.py @@ -1,9 +1,79 @@ #-*- coding: utf-8 -*- -from PIL import Image, ImageChops, ImageDraw +from PIL import Image, ImageDraw from django.contrib.auth.models import User from filer.models.foldermodels import Folder from filer.models.clipboardmodels import Clipboard, ClipboardItem +from django.urls import reverse +from django.contrib.admin import helpers + + +def get_dir_listing_url(folder): + if folder is None: + return reverse('admin:filer-directory_listing-root') + if folder == 'unfiled': + return reverse('admin:filer-directory_listing-unfiled_images') + return reverse('admin:filer-directory_listing', + kwargs={'folder_id': folder.id}) + +def get_make_root_folder_url(): + return reverse('admin:filer-directory_listing-make_root_folder') + + +def filer_obj_as_checkox(filer_obj): + + def filer_object_type(filer_obj): + if isinstance(filer_obj, Folder): + return 'folder' + return 'file' + + return '%s-%d' % (filer_object_type(filer_obj), filer_obj.id) + + +def paste_clipboard_to_folder(client, destination, clipboard): + data_to_post = { 'clipboard_id': clipboard.pk } + if destination: + data_to_post['folder_id'] = destination.id + return client.post( + reverse('admin:filer-paste_clipboard_to_folder'), data_to_post) + + +def move_single_file_to_clipboard_action(client, folder_view, file_to_move): + post_data = {"move-to-clipboard-%d" % (f.id,): '' + for f in file_to_move} + url = get_dir_listing_url(folder_view) + return client.post(url, post_data) + + +def move_to_clipboard_action(client, folder_view, to_move, follow=False): + objects_to_move = [filer_obj_as_checkox(filer_obj) + for filer_obj in to_move] + url = get_dir_listing_url(folder_view) + return client.post(url, { + 'action': 'move_to_clipboard', + 'post': 'yes', + helpers.ACTION_CHECKBOX_NAME: objects_to_move }, follow=follow), url + + +def move_action(client, folder_view, destination, to_move, follow=False): + objects_to_move = [filer_obj_as_checkox(filer_obj) + for filer_obj in to_move] + url = get_dir_listing_url(folder_view) + return client.post(url, { + 'action': 'move_files_and_folders', + 'post': 'yes', + 'destination': destination.id, + helpers.ACTION_CHECKBOX_NAME: objects_to_move }, follow=follow), url + + +def enable_restriction(client, folder_view, filer_objects, follow=True): + url = get_dir_listing_url(folder_view) + return client.post(url, { + 'action': 'enable_restriction', + 'post': 'yes', + helpers.ACTION_CHECKBOX_NAME: [filer_obj_as_checkox(obj) for obj in filer_objects]}, + follow=follow), url + def create_superuser(): superuser = User.objects.create_superuser('admin', @@ -20,11 +90,11 @@ def create_folder_structure(depth=2, sibling=2, parent=None): * parent: is the folder instance of the parent. """ if depth > 0 and sibling > 0: - depth_range = range(1, depth+1) + depth_range = list(range(1, depth+1)) depth_range.reverse() for d in depth_range: for s in range(1,sibling+1): - name = "folder: %s -- %s" %(str(d), str(s)) + name = "%s -- %s" %(str(d), str(s)) folder = Folder(name=name, parent=parent) folder.save() create_folder_structure(depth=d-1, sibling=sibling, parent=folder) @@ -41,3 +111,88 @@ def create_image(mode='RGB', size=(800, 600)): draw.rectangle((x_bit, y_bit * 2, x_bit * 7, y_bit * 3), 'red') draw.rectangle((x_bit * 2, y_bit, x_bit * 3, y_bit * 8), 'red') return image + + +class SettingsOverride(object): + """ + Overrides Django settings within a context and resets them to their inital + values on exit. + + Example: + + with SettingsOverride(DEBUG=True): + # do something + """ + + def __init__(self, settings_module, **overrides): + self.settings_module = settings_module + self.overrides = overrides + + def __call__(self, func): + if isinstance(func, type): + def _pre_setup(test_instance): + self.enable() + func.setUp(test_instance) + def _post_teardown(test_instance): + func.tearDown(test_instance) + self.disable() + # preserve cls name for tests discovery tools + inner = type(func.__name__, (func,), { + 'setUp': _pre_setup, + 'tearDown': _post_teardown, + '__module__': func.__module__, + }) + return inner + else: + @wraps(func) + def inner(*args, **kwargs): + with self: + return func(*args, **kwargs) + return inner + + + def enable(self): + self.old = {} + for key, value in list(self.overrides.items()): + self.old[key] = getattr(self.settings_module, key, None) + setattr(self.settings_module, key, value) + + def disable(self): + for key, value in list(self.old.items()): + if value is not None: + setattr(self.settings_module, key, value) + else: + delattr(self.settings_module,key) + + def __enter__(self): + self.enable() + + def __exit__(self, type, value, traceback): + self.disable() + + +def create_staffuser(user): + user = User.objects.create_user( + username=user, + password='secret', + ) + user.is_staff = True + user.is_active = True + user.save() + return user + + +def create_folder_for_user(foldername, user): + folder = Folder.objects.create( + name=foldername, + owner=user, + ) + return folder + + +def get_user_message(response): + """Helper method to return message from response """ + for c in response.context: + message = [m for m in c.get('messages')][0] + if message: + return message diff --git a/filer/tests/models.py b/filer/tests/models.py index 5e73c7a96..d6f344787 100644 --- a/filer/tests/models.py +++ b/filer/tests/models.py @@ -1,18 +1,45 @@ #-*- coding: utf-8 -*- import os +import tempfile +import urllib.parse +import zipfile +import time + from django.forms.models import modelform_factory +from django.db.models import Q from django.test import TestCase +from django.test.utils import override_settings from django.core.files import File as DjangoFile +from django.core.exceptions import ValidationError +from django.contrib.admin import helpers +from django.core import files as dj_files +from filer import settings as filer_settings from filer.models.foldermodels import Folder from filer.models.imagemodels import Image from filer.models.filemodels import File +from filer.models.archivemodels import Archive from filer.models.clipboardmodels import Clipboard -from filer.tests.helpers import (create_superuser, create_folder_structure, - create_image, create_clipboard_item) -from filer import settings as filer_settings +from filer.tests.helpers import ( + get_dir_listing_url, create_superuser, create_folder_structure, + create_image, create_clipboard_item, SettingsOverride, + filer_obj_as_checkox) +from filer.utils.generate_filename import by_path +def create_filer_image_obj(image_name, size=(800, 600), **kwargs): + image = create_image() + image_path = os.path.join(os.path.dirname(__file__), image_name) + image.save(image_path, 'JPEG') + file_obj = DjangoFile(open(image_path, 'rb'), name=image_name) + kwargs.update({ + 'original_filename': image_name, + 'file': file_obj + }) + image = Image.objects.create(**kwargs) + os.remove(image_path) + return image + class FilerApiTests(TestCase): @@ -22,17 +49,17 @@ def setUp(self): self.img = create_image() self.image_name = 'test_file.jpg' self.filename = os.path.join(os.path.dirname(__file__), - self.image_name) + self.image_name) self.img.save(self.filename, 'JPEG') def tearDown(self): self.client.logout() os.remove(self.filename) - for f in File.objects.all(): - f.delete() + for f in File.all_objects.all(): + f.delete(to_trash=False) def create_filer_image(self): - file_obj= DjangoFile(open(self.filename), name=self.image_name) + file_obj = DjangoFile(open(self.filename, 'rb'), name=self.image_name) image = Image.objects.create(owner=self.superuser, original_filename=self.image_name, file=file_obj) @@ -48,16 +75,16 @@ def test_create_and_delete_image(self): image.save() self.assertEqual(Image.objects.count(), 1) image = Image.objects.all()[0] - image.delete() + image.delete(to_trash=False) self.assertEqual(Image.objects.count(), 0) def test_upload_image_form(self): self.assertEqual(Image.objects.count(), 0) - file_obj = DjangoFile(open(self.filename), name=self.image_name) + file_obj = DjangoFile(open(self.filename, 'rb'), name=self.image_name) ImageUploadForm = modelform_factory(Image, fields=('original_filename', 'owner', 'file')) upoad_image_form = ImageUploadForm({'original_filename':self.image_name, - 'owner': self.superuser.pk}, - {'file':file_obj}) + 'owner': self.superuser.pk}, + {'file':file_obj}) if upoad_image_form.is_valid(): image = upoad_image_form.save() self.assertEqual(Image.objects.count(), 1) @@ -67,7 +94,7 @@ def test_create_clipboard_item(self): image.save() # Get the clipboard of the current user clipboard_item = create_clipboard_item(user=self.superuser, - file_obj=image) + file_obj=image) clipboard_item.save() self.assertEqual(Clipboard.objects.count(), 1) @@ -79,7 +106,7 @@ def test_create_icons(self): self.assertEqual(len(icons), len(filer_settings.FILER_ADMIN_ICON_SIZES)) for size in filer_settings.FILER_ADMIN_ICON_SIZES: self.assertEqual(os.path.basename(icons[size]), - file_basename + u'__%sx%s_q85_crop_upscale.jpg' %(size,size)) + file_basename + '__%sx%s_q85_crop_subsampling-2_upscale.jpg' %(size,size)) def test_file_upload_public_destination(self): """ @@ -112,12 +139,28 @@ def test_file_move_location(self): image.save() self.assertTrue(image.file.path.startswith(filer_settings.FILER_PUBLICMEDIA_STORAGE.location)) + def test_folder_rename_updates_file_urls(self): + with SettingsOverride(filer_settings, + FILER_PUBLICMEDIA_UPLOAD_TO=by_path, + FOLDER_AFFECTS_URL=True): + folder = Folder(name='foo') + folder.save() + file_obj = DjangoFile(open(self.filename, 'rb'), name=self.image_name) + afile = File(name='testfile', folder=folder, file=file_obj) + afile.save() + self.assertIn('foo/{}'.format(afile.actual_name), afile.url) + folder.name = 'bar' + folder.save() + # refetch from db + afile = File.objects.get(pk=afile.pk) + self.assertIn('bar/{}'.format(afile.actual_name), afile.url) + def test_file_change_upload_to_destination(self): """ Test that the file is actualy move from the private to the public directory when the is_public is checked on an existing private file. """ - file_obj = DjangoFile(open(self.filename), name=self.image_name) + file_obj = DjangoFile(open(self.filename, 'rb'), name=self.image_name) image = Image.objects.create(owner=self.superuser, is_public=False, @@ -134,6 +177,37 @@ def test_file_change_upload_to_destination(self): self.assertTrue(image.file.path.startswith(filer_settings.FILER_PRIVATEMEDIA_STORAGE.location)) self.assertEqual(len(image.icons), len(filer_settings.FILER_ADMIN_ICON_SIZES)) + def test_deleting_folder_deletes_all_files_from_filesystem(self): + folder = Folder.objects.create(name='to_delete') + file_1 = self.create_filer_image() + file_1.folder = folder + file_1.save() + storage, name = file_1.file.storage, file_1.file.name + self.assertTrue(storage.exists(name)) + folder.delete(to_trash=False) + self.assertFalse(storage.exists(name)) + + def test_bulk_deleting_folder_deletes_all_files_from_filesystem(self): + folder = Folder.objects.create(name='to_delete2') + file_1 = self.create_filer_image() + file_1.folder = folder + file_1.save() + storage, name = file_1.file.storage, file_1.file.name + + response = self.client.post(get_dir_listing_url(None), { + 'action': 'delete_files_or_folders', + 'post': 'yes', + helpers.ACTION_CHECKBOX_NAME: filer_obj_as_checkox(folder), + }) + + self.assertTrue(storage.exists('_trash/%s/to_delete2/%s' % ( + file_1.pk, file_1.actual_name))) + self.assertFalse(storage.exists(name)) + folder.delete(to_trash=False) + self.assertFalse(storage.exists(name)) + self.assertFalse(storage.exists('_trash/%s/to_delete2/%s' % ( + file_1.pk, file_1.actual_name))) + def test_deleting_image_deletes_file_from_filesystem(self): file_1 = self.create_filer_image() self.assertTrue(file_1.file.storage.exists(file_1.file.name)) @@ -148,7 +222,7 @@ def test_deleting_image_deletes_file_from_filesystem(self): storage, name = file_1.file.storage, file_1.file.name # delete the file - file_1.delete() + file_1.delete(to_trash=False) # file should be gone self.assertFalse(storage.exists(name)) @@ -171,8 +245,668 @@ def test_deleting_file_does_not_delete_file_from_filesystem_if_other_references_ storage, name = file_1.file.storage, file_1.file.name # delete one file - file_1.delete() + file_1.delete(to_trash=False) # file should still be here self.assertTrue(storage.exists(name)) + def test_credit_text_length_max_size(self): + file_1 = self.create_filer_image() + file_1.full_clean() + file_1.default_credit = '*' * 31 + with self.assertRaises(ValidationError): + file_1.full_clean() + + def test_slash_not_allowed_in_name(self): + file_1 = self.create_filer_image() + file_1.full_clean() + file_1.name = "something/with/slash" + with self.assertRaises(ValidationError): + file_1.full_clean() + + folder = Folder.objects.create( + name="cleaned", site_id=1) + folder.full_clean() + folder.name = "something/with/slash" + with self.assertRaises(ValidationError): + folder.full_clean() + + @override_settings(USE_TZ=True) + def test_cdn_urls(self): + cdn_domain = 'cdn.foobar.com' + with SettingsOverride(filer_settings, + CDN_DOMAIN=cdn_domain, + USE_TZ=True, + CDN_INVALIDATION_TIME=1): + image = self.create_filer_image() + _, netloc, _, _, _, _ = urllib.parse.urlparse(image.url) + self.assertEqual(netloc, '') + time.sleep(1) + _, netloc, _, _, _, _ = urllib.parse.urlparse(image.url) + self.assertEqual(netloc, cdn_domain) + for url in list(image.thumbnails.values()): + _, netloc, _, _, _, _ = urllib.parse.urlparse(url) + self.assertEqual(netloc, cdn_domain) + + @override_settings(USE_TZ=False) + def test_cdn_urls_no_timezone_support(self): + cdn_domain = 'cdn.foobar.com' + with SettingsOverride(filer_settings, + CDN_DOMAIN=cdn_domain, + USE_TZ=False, + CDN_INVALIDATION_TIME=1): + image = self.create_filer_image() + _, netloc, _, _, _, _ = urllib.parse.urlparse(image.url) + self.assertEqual(netloc, '') + time.sleep(1) + _, netloc, _, _, _, _ = urllib.parse.urlparse(image.url) + self.assertEqual(netloc, cdn_domain) + for url in list(image.thumbnails.values()): + _, netloc, _, _, _, _ = urllib.parse.urlparse(url) + self.assertEqual(netloc, cdn_domain) + + +class ArchiveTest(TestCase): + + def setUp(self): + self.entries = [] + self.zipname = 'test.zip' + self.root = root = self.create_and_register_directory(None) + subdir1 = self.create_and_register_directory(root) + subdir2 = self.create_and_register_directory(root) + subdir3 = self.create_and_register_directory(root) + subdir11 = self.create_and_register_directory(subdir1) + subdir12 = self.create_and_register_directory(subdir1) + subdir21 = self.create_and_register_directory(subdir2) + subdir31 = self.create_and_register_directory(subdir3) + leaf1 = self.create_and_register_file(root, 'first leaf') + leaf2 = self.create_and_register_file(subdir11, 'second leaf') + leaf3 = self.create_and_register_file(subdir11, 'third leaf') + leaf4 = self.create_and_register_file(subdir11, 'fourth leaf') + leaf5 = self.create_and_register_file(subdir12, 'fifth leaf') + leaf6 = self.create_and_register_file(subdir2, 'sixth leaf') + leaf7 = self.create_and_register_file(subdir2, 'seventh leaf') + leaf8 = self.create_and_register_file(subdir3, 'eight leaf') + self.create_zipfile() + filer_zipfile = Archive.objects.get() + filer_zipfile.extract() + + def test_collision_when_extracting(self): + foo = Folder.objects.create(name="foo") + # move zip into a folder + archive = Archive.objects.get() + archive.folder = foo + archive.save() + # no collisions should be detected + self.assertEqual(archive.collisions(), []) + # extract zip in the new folder + Archive.objects.get().extract() + # collisions should be detected + self.assertNotEqual(Archive.objects.get().collisions(), []) + # delete foo content and re-try + for a_file in File.objects.exclude(id=archive.id).filter(folder=foo): + a.delete() + for subfolder in Folder.objects.filter(parent=foo): + subfolder.delete() + self.assertEqual(Archive.objects.get().collisions(), []) + + def test_entries_count(self): + files = File.objects.filter(~Q(original_filename=self.zipname)) + tmp_basedir, _ = os.path.split(self.root) + tmp_basedir_comp = tmp_basedir.strip(os.path.sep).split(os.path.sep) + folders = [ff for ff in Folder.objects.exclude(name__in=tmp_basedir_comp) + if ff.pretty_logical_path.startswith(tmp_basedir)] + filer_entries = list(files) + folders + actual = len(filer_entries) + expected = len(self.entries) + self.assertEqual(actual, expected) + + def test_entries_path(self): + files = File.objects.all() + folders = Folder.objects.all() + for entry in self.entries: + basename = os.path.basename(entry) + file_match = files.filter(original_filename=basename) + folder_match = folders.filter(name=basename) + filer_matches = file_match or folder_match + self.assertNotEqual(0, len(filer_matches)) + filer_entry = filer_matches[0] + fields = [x.name for x in filer_entry.logical_path] + fields += [filer_entry.name or filer_entry.original_filename] + filer_path = os.sep + os.sep.join(fields) + self.assertEqual(filer_path, entry) + + def tearDown(self): + os.remove('test.zip') + for f in File.all_objects.all(): + f.delete(to_trash=False) + for entry in reversed(self.entries): + if os.path.isdir(entry): + os.rmdir(entry) + elif os.path.isfile(entry): + os.remove(entry) + + def create_and_register_file(self, parent, data): + fd, path = tempfile.mkstemp(dir=parent) + if isinstance(data, str): + data = data.encode('utf-8') + os.write(fd, data) + os.close(fd) + self.entries.extend([path]) + return path + + def create_and_register_directory(self, parent): + new_dir = tempfile.mkdtemp(dir=parent) + self.entries.extend([new_dir]) + return new_dir + + def create_zipfile(self): + zippy = zipfile.ZipFile(self.zipname, 'w') + for entry in self.entries: + zippy.write(entry) + zippy.close() + file_obj = DjangoFile(open(self.zipname, 'rb'), name=self.zipname) + filer_zipfile = Archive.objects.create( + original_filename=self.zipname, + file=file_obj, + ) + + def test_folder_quoted_logical_path(self): + root_folder = Folder.objects.create(name="Foo's Bar", parent=None) + child = Folder.objects.create(name='Bar"s Foo', parent=root_folder) + self.assertEqual(child.quoted_logical_path, '/Foo%27s%20Bar/Bar%22s%20Foo') + + def test_folder_quoted_logical_path_with_unicode(self): + root_folder = Folder.objects.create(name="Foo's Bar", parent=None) + child = Folder.objects.create(name='Bar"s 日本 Foo', parent=root_folder) + self.assertEqual(child.quoted_logical_path, + '/Foo%27s%20Bar/Bar%22s%20%E6%97%A5%E6%9C%AC%20Foo') + + +@SettingsOverride(filer_settings, + FILER_PUBLICMEDIA_UPLOAD_TO=by_path, + FOLDER_AFFECTS_URL=True) +class TrashableModelTestCase(TestCase): + + def tearDown(self): + for f in File.all_objects.all(): + f.delete(to_trash=False) + + def test_files_deletion_is_soft_by_default(self): + file_foo = File.objects.create( + original_filename='file.txt', + file=dj_files.base.ContentFile(b'some data', name='file.txt')) + file_foo.delete() + self.assertTrue(File.trash.filter(pk=file_foo.pk).exists()) + self.assertFalse(File.objects.filter(pk=file_foo.pk).exists()) + self.assertEqual(File.trash.get(pk=file_foo.pk).file.name, + '_trash/%s/%s' % (file_foo.pk, file_foo.actual_name)) + + def create_filer_image(self, image_name, **kwargs): + return create_filer_image_obj(image_name, **kwargs) + + def test_trashed_files_dont_update_paths_if_tree_changes(self): + img = self.create_filer_image('foo_image.jpg') + folder = Folder.objects.create(name='foo') + img.folder = folder + img.save() + Image.objects.get(id=img.id).delete() + img = Image.trash.get(original_filename='foo_image.jpg') + self.assertEqual(img.file.name, '_trash/%s/foo/%s' % (img.pk, img.actual_name)) + # rename folder + folder.name = 'bar' + # change metadata + folder.restricted = True + # add a parent with a site set + folder.parent = Folder.objects.create( + name='foo', folder_type=Folder.CORE_FOLDER) + folder.save() + # trashed items should preserve metdata but should not change paths + img = Image.trash.get(original_filename='foo_image.jpg') + self.assertEqual(img.file.name, '_trash/%s/foo/%s'% (img.pk, img.actual_name)) + self.assertTrue(img.restricted) + self.assertTrue(img.is_core()) + + def test_file_soft_del_doesnt_remove_file_from_storage_if_other_refs(self): + img1 = self.create_filer_image('foo_image.jpg') + img2 = Image.objects.create(original_filename='foo_image.jpg') + Image.objects.filter(id=img2.id).update(file=img1.file.name) + img2 = Image.objects.get(id=img2.id) + self.assertEqual(img1.file.name, img2.file.name) + self.assertTrue(img1.file.storage.exists(img1.file.name)) + self.assertTrue(img2.file.storage.exists(img2.file.name)) + img2.delete() + img1 = Image.objects.get(original_filename='foo_image.jpg') + self.assertTrue(img1.file.storage.exists(img1.file.name)) + img2 = Image.trash.get(original_filename='foo_image.jpg') + self.assertEqual(img2.file.name, '_trash/%s/%s'% (img2.pk, img2.actual_name)) + + def test_file_soft_del_works_if_file_missing_from_storage(self): + img = self.create_filer_image('foo_image.jpg') + img.file.storage.delete(img.file.name) + img = Image.objects.get(original_filename='foo_image.jpg') + self.assertFalse(img.file.storage.exists(img.file.name)) + img.delete() + img = Image.trash.get(original_filename='foo_image.jpg') + self.assertFalse(img.file.storage.exists(img.file.name)) + self.assertEqual(img.file.name, '_trash/%s/%s' % (img.pk, img.actual_name)) + + def test_thumbnails_removed_when_source_is_soft_deleted(self): + img = self.create_filer_image('foo_image.jpg') + Image.objects.filter(id=img.id).update(owner=create_superuser()) + img = Image.objects.get(id=img.id) + self.assertEqual(sum(1 for i in img.file.get_thumbnails()), 0) + # generate some thumbnails + generated_thumbnails = img.icons + img.file.get_thumbnail({'size': (60, 80)}) + thumb_no = len(filer_settings.FILER_ADMIN_ICON_SIZES) + 1 + self.assertEqual(sum(1 for i in img.file.get_thumbnails()), thumb_no) + img.delete() + # soft deletes files shoudn't be able to generate thumbnails + self.assertEqual(sum(1 for i in img.file.get_thumbnails()), 0) + generated_thumbnails = img.icons + self.assertEqual(img.file.get_thumbnail({'size': (60, 80)}), None) + self.assertEqual(sum(1 for i in img.file.get_thumbnails()), 0) + self.assertEqual(img.url, '') + Image.trash.filter(id=img.id).update(deleted_at=None) + img = Image.objects.get(id=img.id) + img.name = 'asdasda.jpg' + img.save() + # thumbnail generation should work after restoring + generated_thumbnails = img.icons + img.file.get_thumbnail({'size': (60, 80)}) + thumb_no = len(filer_settings.FILER_ADMIN_ICON_SIZES) + 1 + self.assertEqual(sum(1 for i in img.file.get_thumbnails()), thumb_no) + self.assertNotEqual(img.url, '') + + def test_folders_deletion_is_soft_by_default(self): + foo = Folder.objects.create(name='foo') + file_foo = self.create_filer_image('image.jpg') + file_foo.folder = foo + file_foo.save() + file_foo_pk = file_foo.pk + foo_pk = foo.pk + foo.delete() + self.assertTrue(File.trash.filter(pk=file_foo_pk).exists()) + self.assertTrue(Folder.trash.filter(pk=foo_pk).exists()) + self.assertFalse(File.objects.filter(pk=file_foo_pk).exists()) + self.assertFalse(Folder.objects.filter(pk=foo_pk).exists()) + self.assertEqual(File.trash.get(pk=file_foo_pk).file.name, + '_trash/%s/foo/%s' % (file_foo_pk, file_foo.actual_name)) + + def test_restore_clipboard_file_missing_user(self): + from filer.models.tools import get_user_clipboard, delete_clipboard + user = create_superuser() + foo = self.create_filer_image('foo.jpg', owner=user) + clipboard = get_user_clipboard(user) + clipboard.append_file(foo) + delete_clipboard(clipboard) + user.delete() + File.trash.get(id=foo.id).restore() + foo = File.objects.get(id=foo.id) + self.assertEqual(foo.file.name, + '_clipboard/_missing_owner/{}'.format(foo.clean_actual_name)) + + def test_file_restore_moves_file_on_storage(self): + foo = Folder.objects.create(name='foo') + foo_img = self.create_filer_image('foo.jpg', folder=foo) + storage = foo_img.file.storage + alive_path = 'foo/{}_foo.jpg'.format(foo_img.sha1[:10]) + trashed_path = '_trash/{}/{}'.format(foo_img.pk, alive_path) + self.assertEqual(foo_img.file.name, alive_path) + self.assertTrue(storage.exists(alive_path)) + self.assertFalse(storage.exists(trashed_path)) + foo.delete() + self.assertFalse(storage.exists(alive_path)) + self.assertTrue(storage.exists(trashed_path)) + File.trash.get(id=foo_img.id).restore() + self.assertTrue(storage.exists(alive_path)) + self.assertFalse(storage.exists(trashed_path)) + # thumbnails should get generated + foo_img = File.objects.get(id=foo_img.id) + self.assertEqual(sum(1 for i in foo_img.file.get_thumbnails()), 0) + generated_thumbnails = foo_img.icons + foo_img.file.get_thumbnail({'size': (60, 80)}) + thumb_no = len(filer_settings.FILER_ADMIN_ICON_SIZES) + 1 + self.assertEqual(sum(1 for i in foo_img.file.get_thumbnails()), thumb_no) + + def test_restore_clipboard_file(self): + from filer.models.tools import get_user_clipboard, delete_clipboard + user = create_superuser() + foo = self.create_filer_image('foo.jpg', owner=user) + clipboard = get_user_clipboard(user) + self.assertEqual(clipboard.files.count(), 0) + clipboard.append_file(foo) + delete_clipboard(clipboard) + self.assertEqual(clipboard.files.count(), 0) + File.trash.get(id=foo.id).restore() + self.assertEqual(clipboard.files.count(), 1) + foo = File.objects.get(id=foo.id) + self.assertEqual(foo.file.name, + '_clipboard/%s/%s' % (user.username, foo.clean_actual_name)) + + def test_restore_file_with_trashed_folder(self): + foo = Folder.objects.create(name='foo') + bar = Folder.objects.create(name='bar', parent=foo) + foo_img = self.create_filer_image('foo.jpg', folder=foo) + bar_img = self.create_filer_image('bar.jpg', folder=bar) + self.assertEqual(Folder.trash.count() + File.trash.count(), 0) + foo.delete() + self.assertEqual(Folder.trash.count() + File.trash.count(), 4) + File.trash.get(id=bar_img.id).restore() + self.assertEqual(Folder.objects.count() + File.objects.count(), 3) + # foo image should still be in trash since only folders path to + # bar file were restored + File.trash.get(id=foo_img.id) + self.assertEqual(File.objects.get(id=bar_img.id).file.name, + 'foo/bar/{}'.format(bar_img.actual_name)) + + def test_restore_file_with_alive_folder(self): + foo = Folder.objects.create(name='foo') + bar = Folder.objects.create(name='bar', parent=foo) + foo_img = self.create_filer_image('foo.jpg', folder=foo) + bar_img = self.create_filer_image('bar.jpg', folder=bar) + self.assertEqual(Folder.trash.count() + File.trash.count(), 0) + bar_img = File.objects.get(id=bar_img.id) + bar_img.delete() + self.assertEqual(File.trash.get(id=bar_img.id).file.name, + '_trash/%s/foo/bar/%s' % (bar_img.id, bar_img.actual_name)) + self.assertEqual(Folder.trash.count() + File.trash.count(), 1) + File.trash.get(id=bar_img.id).restore() + self.assertEqual(File.objects.get(id=foo_img.id).file.name, + 'foo/{}'.format(foo_img.actual_name)) + self.assertEqual(File.objects.get(id=bar_img.id).file.name, + 'foo/bar/{}'.format(bar_img.actual_name)) + + def test_restore_clipboard_file_where_location_not_available(self): + from filer.models.tools import get_user_clipboard, delete_clipboard + user = create_superuser() + foo = self.create_filer_image('foo.jpg', owner=user) + clipboard = get_user_clipboard(user) + self.assertEqual(clipboard.files.count(), 0) + clipboard.append_file(foo) + delete_clipboard(clipboard) + self.assertEqual(clipboard.files.count(), 0) + # add file to the same location as foo + foo_duplicate = self.create_filer_image('foo.jpg', owner=user) + clipboard.append_file(foo_duplicate) + self.assertEqual(foo_duplicate.file.name, + '_clipboard/%s/foo.jpg' % user.username) + self.assertEqual(clipboard.files.count(), 1) + # restore foo + File.trash.get(id=foo.id).restore() + self.assertEqual(clipboard.files.count(), 2) + self.assertEqual(File.objects.get(id=foo.id).file.name, + '_clipboard/%s/foo_1.jpg' % user.username) + self.assertEqual(File.objects.get(id=foo_duplicate.id).file.name, + '_clipboard/%s/foo.jpg' % user.username) + + def test_restore_file_where_file_location_not_available(self): + foo = Folder.objects.create(name='foo') + bar = Folder.objects.create(name='bar', parent=foo) + foo_img = self.create_filer_image('foo.jpg', folder=foo) + bar_img = self.create_filer_image('bar.jpg', folder=bar) + self.assertEqual(Folder.trash.count() + File.trash.count(), 0) + File.objects.get(id=bar_img.id).delete() + bar_img_duplicate = self.create_filer_image('bar.jpg', folder=bar) + File.trash.get(id=bar_img.id).restore() + self.assertEqual(File.objects.get(id=bar_img_duplicate.id).file.name, + 'foo/bar/{}_bar.jpg'.format(bar_img_duplicate.sha1[:10])) + self.assertEqual(File.objects.get(id=bar_img.id).file.name, + 'foo/bar/{}_bar_1.jpg'.format(bar_img_duplicate.sha1[:10])) + + def test_restore_file_where_file_path_location_not_available(self): + foo = Folder.objects.create(name='foo') + bar = Folder.objects.create(name='bar', parent=foo) + foo_img = self.create_filer_image('foo.jpg', folder=foo) + bar_img = self.create_filer_image('bar.jpg', folder=bar) + self.assertEqual(Folder.trash.count() + File.trash.count(), 0) + foo.delete() + foo_duplicate = Folder.objects.create(name='foo') + bar_duplicate = Folder.objects.create(name='bar', parent=foo_duplicate) + File.trash.get(id=bar_img.id).restore() + self.assertEqual(File.objects.get(id=bar_img.id).file.name, + 'foo_1/bar/{}'.format(bar_img.actual_name)) + self.assertEqual(Folder.trash.count() + File.trash.count(), 1) + self.assertEqual(Folder.objects.count(), 4) + + def test_restore_empty_folder(self): + foo = Folder.objects.create(name='foo') + bar = Folder.objects.create(name='bar', parent=foo) + bar_img = self.create_filer_image('bar.jpg', folder=bar) + baz = Folder.objects.create(name='baz', parent=foo) + self.assertEqual(Folder.objects.count(), 3) + foo.delete() + self.assertEqual(Folder.objects.count(), 0) + Folder.trash.get(id=foo.id).restore() + self.assertEqual(Folder.objects.count(), 3) + bar_img = File.objects.get(id=bar_img.id) + self.assertEqual(bar_img.file.name, 'foo/bar/{}'.format(bar_img.actual_name)) + # add file/folder to the empty folder make sure it works after restore + foo_img = self.create_filer_image('foo.jpg', folder=foo) + self.assertEqual(foo_img.file.name, 'foo/{}'.format(foo_img.actual_name)) + baz_img = self.create_filer_image('baz.jpg', folder=baz) + self.assertEqual(baz_img.file.name, 'foo/baz/{}'.format(baz_img.actual_name)) + baz_child = Folder.objects.create(name='baz', parent=baz) + baz_child_img = self.create_filer_image('baz.jpg', folder=baz_child) + self.assertEqual(baz_child_img.file.name, + 'foo/baz/baz/{}'.format(baz_child_img.actual_name)) + + def test_restore_folder_at_unavailable_location(self): + foo = Folder.objects.create(name='foo') + bar = Folder.objects.create(name='bar', parent=foo) + baz = Folder.objects.create(name='baz', parent=bar) + bar.delete() + # make restore location unavailable + Folder.objects.create(name='bar', parent=foo) + Folder.trash.get(id=bar.id).restore() + bar = Folder.objects.get(id=bar.id) + self.assertEqual(bar.name, 'bar_1') + baz = Folder.objects.get(id=baz.id) + self.assertEqual(baz.pretty_logical_path, '/foo/bar_1/baz') + + def test_folder_restore_restores_all_files(self): + foo = Folder.objects.create(name='foo') + bar = Folder.objects.create(name='bar', parent=foo) + baz = Folder.objects.create(name='baz', parent=bar) + foo_img = self.create_filer_image('foo.jpg', folder=foo) + bar_img = self.create_filer_image('bar.jpg', folder=bar) + baz_img = self.create_filer_image('baz.jpg', folder=baz) + foo_img1 = self.create_filer_image('foo1.jpg', folder=foo) + bar_img1 = self.create_filer_image('bar1.jpg', folder=bar) + baz_img1 = self.create_filer_image('baz1.jpg', folder=baz) + self.assertEqual(Folder.objects.count()+File.objects.count(), 9) + foo.delete() + self.assertEqual(Folder.objects.count()+File.objects.count(), 0) + Folder.trash.get(id=foo.id).restore() + self.assertEqual(Folder.objects.count()+File.objects.count(), 9) + foo = Folder.objects.get(id=foo.id) + self.assertEqual(foo.get_descendants(include_self=True).count(), 3) + self.assertEqual(File.objects.get(id=foo_img.id).file.name, + 'foo/{}'.format(foo_img.actual_name)) + self.assertEqual(File.objects.get(id=foo_img1.id).file.name, + 'foo/{}'.format(foo_img1.actual_name)) + self.assertEqual(File.objects.get(id=bar_img.id).file.name, + 'foo/bar/{}'.format(bar_img.actual_name)) + self.assertEqual(File.objects.get(id=bar_img1.id).file.name, + 'foo/bar/{}'.format(bar_img1.actual_name)) + self.assertEqual(File.objects.get(id=baz_img.id).file.name, + 'foo/bar/baz/{}'.format(baz_img.actual_name)) + self.assertEqual(File.objects.get(id=baz_img1.id).file.name, + 'foo/bar/baz/{}'.format(baz_img1.actual_name)) + + def test_restore_folder_with_duplicated_children(self): + foo = Folder.objects.create(name='foo') + bar = Folder.objects.create(name='bar', parent=foo) + foo_img = self.create_filer_image('foo.jpg', folder=foo) + bar_img = self.create_filer_image('bar.jpg', folder=bar) + bar.delete() + new_bar = Folder.objects.create(name='bar', parent=foo) + new_bar_img = self.create_filer_image('bar.jpg', folder=new_bar) + new_bar.delete() + foo.delete() + self.assertEqual(Folder.objects.count()+File.objects.count(), 0) + Folder.trash.get(id=foo.id).restore() + self.assertEqual(Folder.objects.count()+File.objects.count(), 6) + bar_folder_names = Folder.objects.filter( + parent=foo.id).values_list('name', flat=True) + self.assertEqual(len(bar_folder_names), 2) + self.assertEqual(sorted(['bar', 'bar_1']), sorted(bar_folder_names)) + self.assertEqual(File.objects.get(id=foo_img.id).file.name, + 'foo/{}'.format(foo_img.actual_name)) + self.assertEqual(File.objects.get(id=bar_img.id).file.name, + 'foo/bar/{}'.format(bar_img.actual_name)) + self.assertEqual(File.objects.get(id=new_bar_img.id).file.name, + 'foo/bar_1/{}'.format(new_bar_img.actual_name)) + + def test_folder_save_with_trashed_subfolder(self): + foo = Folder.objects.create(name='foo') + foo_child = Folder.objects.create(name='foo_child', parent=foo) + foo_child2 = Folder.objects.create(name='foo_child2', parent=foo_child) + foo_child.delete() + foo.shared.add(1) + foo.restricted = True + foo.save() + + +@SettingsOverride(filer_settings, + FILER_PUBLICMEDIA_UPLOAD_TO=by_path, + FOLDER_AFFECTS_URL=True) +class TestFileModel(TestCase): + + def setUp(self): + self.superuser = create_superuser() + self.img_width = 400 + + def tearDown(self): + for filer_file in File.all_objects.all(): + filer_file.delete(to_trash=False) + + def create_filer_image(self, image_name, **kwargs): + self.img_width += 100 + return create_filer_image_obj(image_name, + size=(self.img_width, 400), + **kwargs) + + def store_file_data(self, file_obj, clean_actual_name=None, db_reload=True): + if db_reload: + file_obj = File.all_objects.get(id=file_obj.id) + return (file_obj.name, + file_obj.folder, + file_obj.original_filename, + clean_actual_name or file_obj.clean_actual_name, + file_obj.actual_name, + file_obj.file.name) + + def test_set_names_for_restore_folder(self): + img_name = 'foo.jpg' + foo = Folder.objects.create(name='foo') + foo_img = self.create_filer_image(img_name, folder=foo) + test_file = File(name="bar.jpg", folder=foo, original_filename='test.jpg') + test_file._set_valid_name_for_restore() + self.assertEqual(test_file.name, "bar.jpg") + self.assertEqual(test_file.original_filename, "test.jpg") + test_file.name = img_name + test_file._set_valid_name_for_restore() + self.assertEqual(test_file.name, "foo_1.jpg") + self.assertEqual(test_file.original_filename, "test.jpg") + test_file.name = None + test_file._set_valid_name_for_restore() + self.assertEqual(test_file.name, None) + self.assertEqual(test_file.original_filename, "test.jpg") + test_file.original_filename = img_name + test_file._set_valid_name_for_restore() + self.assertEqual(test_file.name, None) + self.assertEqual(test_file.original_filename, "foo_1.jpg") + + def test_set_names_for_restore_clipboard(self): + img_name = 'foo.jpg' + foo = Folder.objects.create(name='foo') + foo_img = self.create_filer_image(img_name, folder=foo) + create_clipboard_item(user=self.superuser, file_obj=foo_img).save() + test_file = File(name="bar.jpg", + folder=None, + original_filename='test.jpg', + owner=self.superuser) + test_file._set_valid_name_for_restore() + self.assertEqual(test_file.name, "bar.jpg") + self.assertEqual(test_file.original_filename, "test.jpg") + test_file.name = img_name + test_file._set_valid_name_for_restore() + self.assertEqual(test_file.name, "foo_1.jpg") + self.assertEqual(test_file.original_filename, "test.jpg") + test_file.name = None + test_file._set_valid_name_for_restore() + self.assertEqual(test_file.name, None) + self.assertEqual(test_file.original_filename, "test.jpg") + test_file.original_filename = img_name + test_file._set_valid_name_for_restore() + self.assertEqual(test_file.name, None) + self.assertEqual(test_file.original_filename, "foo_1.jpg") + + def test_set_names_for_restore_unfiled(self): + img_name = 'foo.jpg' + foo_img = self.create_filer_image(img_name) + test_file = File(name="bar.jpg", + folder=None, + original_filename='test.jpg', + owner=None) + test_file._set_valid_name_for_restore() + self.assertEqual(test_file.name, "bar.jpg") + self.assertEqual(test_file.original_filename, "test.jpg") + test_file.name = img_name + test_file._set_valid_name_for_restore() + self.assertEqual(test_file.name, "foo_1.jpg") + self.assertEqual(test_file.original_filename, "test.jpg") + test_file.name = None + test_file._set_valid_name_for_restore() + self.assertEqual(test_file.name, None) + self.assertEqual(test_file.original_filename, "test.jpg") + test_file.original_filename = img_name + test_file._set_valid_name_for_restore() + self.assertEqual(test_file.name, None) + self.assertEqual(test_file.original_filename, "foo_1.jpg") + + def test_restore_with_hash_names(self): + img_name = 'foo.jpg' + foo = Folder.objects.create(name='foo') + foo_img = self.create_filer_image(img_name, folder=foo) + initial = self.store_file_data(foo) + foo_img = File.objects.get(id=foo_img.id) # necessary before delete + foo_img.delete() + self.create_filer_image('bar.jpg', folder=foo) + self.assertNotEqual(self.store_file_data(foo_img), initial) + foo_img.restore() + self.assertEqual(self.store_file_data(foo_img), initial) + foo_img.delete() + foo2_img = self.create_filer_image(img_name, folder=foo) + self.assertEqual(foo2_img.clean_actual_name, img_name) + self.assertEqual(foo2_img.clean_actual_name, img_name) + self.assertEqual(foo2_img.actual_name, foo_img.actual_name) + foo_img.restore() + self.assertEqual(File.objects.get(id=foo_img.id).clean_actual_name, 'foo_1.jpg') + self.assertNotEqual(foo2_img.actual_name, foo_img.actual_name) + + def test_filename_properties(self): + file1 = File(name='', + folder=None, + original_filename='original.txt') + self.assertEqual(file1.clean_actual_name, 'original.txt') + self.assertEqual(file1.actual_name, 'original.txt') + self.assertEqual(file1.upload_to_name, file1.clean_actual_name) + file1.sha1 = 'randomdatastring' + self.assertEqual(file1.clean_actual_name, 'original.txt') + self.assertEqual(file1.actual_name, 'randomdata_original.txt') + self.assertEqual(file1.upload_to_name, file1.clean_actual_name) + file1.name = 'name.txt' + self.assertEqual(file1.clean_actual_name, 'name.txt') + self.assertEqual(file1.actual_name, 'randomdata_name.txt') + self.assertEqual(file1.upload_to_name, file1.clean_actual_name) + file1.name = 'name' + self.assertEqual(file1.clean_actual_name, 'name') + self.assertEqual(file1.actual_name, 'randomdata_name') + self.assertEqual(file1.upload_to_name, file1.clean_actual_name) + file1.folder = Folder() + self.assertEqual(file1.clean_actual_name, 'name') + self.assertEqual(file1.actual_name, 'randomdata_name') + self.assertEqual(file1.upload_to_name, file1.actual_name) diff --git a/filer/tests/permissions.py b/filer/tests/permissions.py deleted file mode 100644 index 5246e9c5a..000000000 --- a/filer/tests/permissions.py +++ /dev/null @@ -1,310 +0,0 @@ -#-*- coding: utf-8 -*- -from django.contrib.auth.models import User, Group -from django.core.files import File as DjangoFile -from django.test.testcases import TestCase -from filer import settings as filer_settings -from filer.models.clipboardmodels import Clipboard -from filer.models.foldermodels import Folder, FolderPermission -from filer.models.imagemodels import Image -from filer.tests.utils import Mock -from filer.tests.helpers import create_image, create_superuser -import os - -class FolderPermissionsTestCase(TestCase): - - def setUp(self): - self.superuser = create_superuser() - self.client.login(username='admin', password='secret') - - self.unauth_user = User.objects.create(username='unauth_user') - - self.owner = User.objects.create(username='owner') - - self.test_user1 = User.objects.create(username='test1', password='secret') - self.test_user2 = User.objects.create(username='test2', password='secret') - - self.group1 = Group.objects.create(name='name1') - self.group2 = Group.objects.create(name='name2') - - self.test_user1.groups.add(self.group1) - self.test_user2.groups.add(self.group2) - - self.img = create_image() - self.image_name = 'test_file.jpg' - self.filename = os.path.join(os.path.dirname(__file__), - self.image_name) - self.img.save(self.filename, 'JPEG') - - self.file = DjangoFile(open(self.filename), name=self.image_name) - # This is actually a "file" for filer considerations - self.image = Image.objects.create(owner=self.superuser, - original_filename=self.image_name, - file=self.file) - self.clipboard = Clipboard.objects.create(user=self.superuser) - self.clipboard.append_file(self.image) - - self.folder = Folder.objects.create(name='test_folder') - - self.folder_perm = Folder.objects.create(name='test_folder2') - - def tearDown(self): - self.image.delete() - - def test_superuser_has_rights(self): - request = Mock() - setattr(request, 'user', self.superuser) - - result = self.folder.has_read_permission(request) - self.assertEqual(result, True) - - def test_unlogged_user_has_no_rights(self): - old_setting = filer_settings.FILER_ENABLE_PERMISSIONS - try: - filer_settings.FILER_ENABLE_PERMISSIONS = True - request = Mock() - setattr(request, 'user', self.unauth_user) - - result = self.folder.has_read_permission(request) - self.assertEqual(result, False) - finally: - filer_settings.FILER_ENABLE_PERMISSIONS = old_setting - - def test_unlogged_user_has_rights_when_permissions_disabled(self): - request = Mock() - setattr(request, 'user', self.unauth_user) - - result = self.folder.has_read_permission(request) - self.assertEqual(result, True) - - def test_owner_user_has_rights(self): - # Set owner as the owner of the folder. - self.folder.owner = self.owner - request = Mock() - setattr(request, 'user', self.owner) - - result = self.folder.has_read_permission(request) - self.assertEqual(result, True) - - def test_combined_groups(self): - request1 = Mock() - setattr(request1, 'user', self.test_user1) - request2 = Mock() - setattr(request2, 'user', self.test_user2) - - old_setting = filer_settings.FILER_ENABLE_PERMISSIONS - try: - filer_settings.FILER_ENABLE_PERMISSIONS = True - - self.assertEqual(self.folder.has_read_permission(request1), False) - self.assertEqual(self.folder.has_read_permission(request2), False) - self.assertEqual(self.folder_perm.has_read_permission(request1), False) - self.assertEqual(self.folder_perm.has_read_permission(request2), False) - - self.assertEqual(FolderPermission.objects.count(), 0) - - FolderPermission.objects.create(folder=self.folder, type=FolderPermission.CHILDREN, group=self.group1, can_edit=FolderPermission.DENY, can_read=FolderPermission.ALLOW, can_add_children=FolderPermission.DENY) - FolderPermission.objects.create(folder=self.folder_perm, type=FolderPermission.CHILDREN, group=self.group2, can_edit=FolderPermission.DENY, can_read=FolderPermission.ALLOW, can_add_children=FolderPermission.DENY) - - self.assertEqual(FolderPermission.objects.count(), 2) - - # We have to invalidate cache - delattr(self.folder, 'permission_cache') - delattr(self.folder_perm, 'permission_cache') - - self.assertEqual(self.folder.has_read_permission(request1), True) - self.assertEqual(self.folder.has_read_permission(request2), False) - self.assertEqual(self.folder_perm.has_read_permission(request1), False) - self.assertEqual(self.folder_perm.has_read_permission(request2), True) - - self.test_user1.groups.add(self.group2) - self.test_user2.groups.add(self.group1) - - # We have to invalidate cache - delattr(self.folder, 'permission_cache') - delattr(self.folder_perm, 'permission_cache') - - self.assertEqual(self.folder.has_read_permission(request1), True) - self.assertEqual(self.folder.has_read_permission(request2), True) - self.assertEqual(self.folder_perm.has_read_permission(request1), True) - self.assertEqual(self.folder_perm.has_read_permission(request2), True) - - finally: - filer_settings.FILER_ENABLE_PERMISSIONS = old_setting - - def test_overlapped_groups_deny1(self): - # Tests overlapped groups with explicit deny - - request1 = Mock() - setattr(request1, 'user', self.test_user1) - - old_setting = filer_settings.FILER_ENABLE_PERMISSIONS - try: - filer_settings.FILER_ENABLE_PERMISSIONS = True - - self.assertEqual(self.folder.has_read_permission(request1), False) - self.assertEqual(self.folder_perm.has_read_permission(request1), False) - - self.assertEqual(FolderPermission.objects.count(), 0) - - FolderPermission.objects.create(folder=self.folder, type=FolderPermission.CHILDREN, group=self.group1, can_edit=FolderPermission.DENY, can_read=FolderPermission.ALLOW, can_add_children=FolderPermission.DENY) - FolderPermission.objects.create(folder=self.folder, type=FolderPermission.CHILDREN, group=self.group2, can_edit=FolderPermission.ALLOW, can_read=FolderPermission.ALLOW, can_add_children=FolderPermission.ALLOW) - - self.assertEqual(FolderPermission.objects.count(), 2) - - # We have to invalidate cache - delattr(self.folder, 'permission_cache') - - self.assertEqual(self.test_user1.groups.filter(pk=self.group1.pk).exists(), True) - self.assertEqual(self.test_user1.groups.filter(pk=self.group2.pk).exists(), False) - - self.assertEqual(self.folder.has_read_permission(request1), True) - self.assertEqual(self.folder.has_edit_permission(request1), False) - - self.assertEqual(self.test_user1.groups.count(), 1) - - self.test_user1.groups.add(self.group2) - - self.assertEqual(self.test_user1.groups.count(), 2) - - # We have to invalidate cache - delattr(self.folder, 'permission_cache') - - self.assertEqual(self.folder.has_read_permission(request1), True) - self.assertEqual(self.folder.has_edit_permission(request1), False) - - finally: - filer_settings.FILER_ENABLE_PERMISSIONS = old_setting - - def test_overlapped_groups_deny2(self): - # Tests overlapped groups with explicit deny - # Similar test to test_overlapped_groups_deny1, only order of groups is different - - request2 = Mock() - setattr(request2, 'user', self.test_user2) - - old_setting = filer_settings.FILER_ENABLE_PERMISSIONS - try: - filer_settings.FILER_ENABLE_PERMISSIONS = True - - self.assertEqual(self.folder.has_read_permission(request2), False) - self.assertEqual(self.folder_perm.has_read_permission(request2), False) - - self.assertEqual(FolderPermission.objects.count(), 0) - - FolderPermission.objects.create(folder=self.folder_perm, type=FolderPermission.CHILDREN, group=self.group2, can_edit=FolderPermission.DENY, can_read=FolderPermission.ALLOW, can_add_children=FolderPermission.DENY) - FolderPermission.objects.create(folder=self.folder_perm, type=FolderPermission.CHILDREN, group=self.group1, can_edit=FolderPermission.ALLOW, can_read=FolderPermission.ALLOW, can_add_children=FolderPermission.ALLOW) - - self.assertEqual(FolderPermission.objects.count(), 2) - - # We have to invalidate cache - delattr(self.folder_perm, 'permission_cache') - - self.assertEqual(self.test_user2.groups.filter(pk=self.group2.pk).exists(), True) - self.assertEqual(self.test_user2.groups.filter(pk=self.group1.pk).exists(), False) - - self.assertEqual(self.folder_perm.has_read_permission(request2), True) - self.assertEqual(self.folder_perm.has_edit_permission(request2), False) - - self.assertEqual(self.test_user2.groups.count(), 1) - - self.test_user2.groups.add(self.group1) - - self.assertEqual(self.test_user2.groups.count(), 2) - - # We have to invalidate cache - delattr(self.folder_perm, 'permission_cache') - - self.assertEqual(self.folder_perm.has_read_permission(request2), True) - self.assertEqual(self.folder_perm.has_edit_permission(request2), False) - - finally: - filer_settings.FILER_ENABLE_PERMISSIONS = old_setting - - def test_overlapped_groups1(self): - # Tests overlapped groups without explicit deny - - request1 = Mock() - setattr(request1, 'user', self.test_user1) - - old_setting = filer_settings.FILER_ENABLE_PERMISSIONS - try: - filer_settings.FILER_ENABLE_PERMISSIONS = True - - self.assertEqual(self.folder.has_read_permission(request1), False) - self.assertEqual(self.folder_perm.has_read_permission(request1), False) - - self.assertEqual(FolderPermission.objects.count(), 0) - - FolderPermission.objects.create(folder=self.folder, type=FolderPermission.CHILDREN, group=self.group1, can_edit=None, can_read=FolderPermission.ALLOW, can_add_children=None) - FolderPermission.objects.create(folder=self.folder, type=FolderPermission.CHILDREN, group=self.group2, can_edit=FolderPermission.ALLOW, can_read=FolderPermission.ALLOW, can_add_children=FolderPermission.ALLOW) - - self.assertEqual(FolderPermission.objects.count(), 2) - - # We have to invalidate cache - delattr(self.folder, 'permission_cache') - - self.assertEqual(self.test_user1.groups.filter(pk=self.group1.pk).exists(), True) - self.assertEqual(self.test_user1.groups.filter(pk=self.group2.pk).exists(), False) - - self.assertEqual(self.folder.has_read_permission(request1), True) - self.assertEqual(self.folder.has_edit_permission(request1), False) - - self.assertEqual(self.test_user1.groups.count(), 1) - - self.test_user1.groups.add(self.group2) - - self.assertEqual(self.test_user1.groups.count(), 2) - - # We have to invalidate cache - delattr(self.folder, 'permission_cache') - - self.assertEqual(self.folder.has_read_permission(request1), True) - self.assertEqual(self.folder.has_edit_permission(request1), True) - - finally: - filer_settings.FILER_ENABLE_PERMISSIONS = old_setting - - def test_overlapped_groups2(self): - # Tests overlapped groups without explicit deny - # Similar test to test_overlapped_groups1, only order of groups is different - - request2 = Mock() - setattr(request2, 'user', self.test_user2) - - old_setting = filer_settings.FILER_ENABLE_PERMISSIONS - try: - filer_settings.FILER_ENABLE_PERMISSIONS = True - - self.assertEqual(self.folder.has_read_permission(request2), False) - self.assertEqual(self.folder_perm.has_read_permission(request2), False) - - self.assertEqual(FolderPermission.objects.count(), 0) - - FolderPermission.objects.create(folder=self.folder_perm, type=FolderPermission.CHILDREN, group=self.group2, can_edit=None, can_read=FolderPermission.ALLOW, can_add_children=None) - FolderPermission.objects.create(folder=self.folder_perm, type=FolderPermission.CHILDREN, group=self.group1, can_edit=FolderPermission.ALLOW, can_read=FolderPermission.ALLOW, can_add_children=FolderPermission.ALLOW) - - self.assertEqual(FolderPermission.objects.count(), 2) - - # We have to invalidate cache - delattr(self.folder_perm, 'permission_cache') - - self.assertEqual(self.test_user2.groups.filter(pk=self.group2.pk).exists(), True) - self.assertEqual(self.test_user2.groups.filter(pk=self.group1.pk).exists(), False) - - self.assertEqual(self.folder_perm.has_read_permission(request2), True) - self.assertEqual(self.folder_perm.has_edit_permission(request2), False) - - self.assertEqual(self.test_user2.groups.count(), 1) - - self.test_user2.groups.add(self.group1) - - self.assertEqual(self.test_user2.groups.count(), 2) - - # We have to invalidate cache - delattr(self.folder_perm, 'permission_cache') - - self.assertEqual(self.folder_perm.has_read_permission(request2), True) - self.assertEqual(self.folder_perm.has_edit_permission(request2), True) - - finally: - filer_settings.FILER_ENABLE_PERMISSIONS = old_setting diff --git a/filer/tests/server_backends.py b/filer/tests/server_backends.py index e7a3593c7..7f04d283e 100644 --- a/filer/tests/server_backends.py +++ b/filer/tests/server_backends.py @@ -1,6 +1,5 @@ #-*- coding: utf-8 -*- import time -import shutil import os from django.core.files.uploadedfile import SimpleUploadedFile from django.http import HttpResponseNotModified, Http404 @@ -20,7 +19,7 @@ def setUp(self): original_filename = 'testimage.jpg' file_obj = SimpleUploadedFile( name=original_filename, - content=create_image().tostring(), + content=create_image().tobytes(), content_type='image/jpeg') self.filer_file = File.objects.create( is_public=False, @@ -28,7 +27,7 @@ def setUp(self): original_filename=original_filename) def tearDown(self): - self.filer_file.delete() + self.filer_file.delete(to_trash=False) class DefaultServerTestCase(BaseServerBackendTestCase): def test_normal(self): @@ -65,7 +64,7 @@ def test_normal(self): request = Mock() request.META = {} response = self.server.serve(request, self.filer_file.file) - headers = dict(response.items()) + headers = dict(list(response.items())) self.assertTrue(response.has_header('X-Accel-Redirect')) self.assertTrue(headers['X-Accel-Redirect'].startswith(self.server.nginx_location)) # make sure the file object was never opened (otherwise the whole delegating to nginx would kinda @@ -81,7 +80,7 @@ def test_missing_file(self): request.META = {} os.remove(self.filer_file.file.path) response = self.server.serve(request, self.filer_file.file) - headers = dict(response.items()) + headers = dict(list(response.items())) self.assertTrue(response.has_header('X-Accel-Redirect')) self.assertTrue(headers['X-Accel-Redirect'].startswith(self.server.nginx_location)) self.assertTrue(self.filer_file.file.closed) @@ -96,7 +95,7 @@ def test_normal(self): request = Mock() request.META = {} response = self.server.serve(request, self.filer_file.file) - headers = dict(response.items()) + headers = dict(list(response.items())) self.assertTrue(response.has_header('X-Sendfile')) self.assertEqual(headers['X-Sendfile'], self.filer_file.file.path) # make sure the file object was never opened (otherwise the whole delegating to nginx would kinda @@ -112,9 +111,9 @@ def test_missing_file(self): request.META = {} os.remove(self.filer_file.file.path) response = self.server.serve(request, self.filer_file.file) - headers = dict(response.items()) + headers = dict(list(response.items())) self.assertTrue(response.has_header('X-Sendfile')) self.assertEqual(headers['X-Sendfile'], self.filer_file.file.path) # make sure the file object was never opened (otherwise the whole delegating to nginx would kinda # be useless) - self.assertTrue(self.filer_file.file.closed) \ No newline at end of file + self.assertTrue(self.filer_file.file.closed) diff --git a/filer/tests/test_cache.py b/filer/tests/test_cache.py new file mode 100644 index 000000000..af3e70272 --- /dev/null +++ b/filer/tests/test_cache.py @@ -0,0 +1,151 @@ +#-*- coding: utf-8 -*- +from unittest.mock import patch, call + +from django.test import TestCase, override_settings + +from filer.utils.cache import ( + invalidate_folder_listing_cache, + invalidate_folder_listing_cache_for_file, + DEFAULT_FOLDER_LISTING_CACHE_KEY, +) + + +class MockFolder: + """Lightweight folder stub to avoid DB hits.""" + def __init__(self, pk, site_id=None, parent=None): + self.pk = pk + self.id = pk + self.site_id = site_id + self.parent = parent + self.parent_id = parent.pk if parent else None + + +class MockFile: + """Lightweight file stub.""" + def __init__(self, folder=None): + self.folder = folder + + +def _key(site_id, folder_id): + return DEFAULT_FOLDER_LISTING_CACHE_KEY.format( + site_id=site_id or '', folder_id=folder_id) + + +class TestInvalidateFolderListingCache(TestCase): + + @patch('filer.utils.cache.cache') + def test_none_folder_is_noop(self, mock_cache): + invalidate_folder_listing_cache(None) + mock_cache.delete.assert_not_called() + + @patch('filer.utils.cache.cache') + def test_virtual_folder_no_pk_is_noop(self, mock_cache): + """FolderRoot / UnfiledImages have no pk.""" + class VirtualFolder: + pass + invalidate_folder_listing_cache(VirtualFolder()) + mock_cache.delete.assert_not_called() + + @patch('filer.utils.cache.cache') + def test_virtual_folder_pk_none_is_noop(self, mock_cache): + folder = MockFolder(pk=None) + invalidate_folder_listing_cache(folder) + mock_cache.delete.assert_not_called() + + @patch('filer.utils.cache.cache') + def test_root_folder_with_site(self, mock_cache): + """Root folder (no parent) with a site invalidates only itself.""" + folder = MockFolder(pk=10, site_id=3) + invalidate_folder_listing_cache(folder) + mock_cache.delete.assert_called_once_with(_key(3, 10)) + + @patch('filer.utils.cache.cache') + def test_root_folder_without_site(self, mock_cache): + """Root folder with no site uses empty string in key.""" + folder = MockFolder(pk=10, site_id=None) + invalidate_folder_listing_cache(folder) + mock_cache.delete.assert_called_once_with(_key(None, 10)) + + @patch('filer.utils.cache.cache') + def test_child_folder_invalidates_self_and_parent(self, mock_cache): + parent = MockFolder(pk=5, site_id=2) + child = MockFolder(pk=15, site_id=2, parent=parent) + invalidate_folder_listing_cache(child) + mock_cache.delete.assert_has_calls([ + call(_key(2, 15)), + call(_key(2, 5)), + ]) + self.assertEqual(mock_cache.delete.call_count, 2) + + @patch('filer.utils.cache.cache') + def test_grandchild_invalidates_self_parent_grandparent(self, mock_cache): + grandparent = MockFolder(pk=1, site_id=7) + parent = MockFolder(pk=5, site_id=7, parent=grandparent) + child = MockFolder(pk=15, site_id=7, parent=parent) + invalidate_folder_listing_cache(child) + mock_cache.delete.assert_has_calls([ + call(_key(7, 15)), + call(_key(7, 5)), + call(_key(7, 1)), + ]) + self.assertEqual(mock_cache.delete.call_count, 3) + + @patch('filer.utils.cache.cache') + def test_parent_without_grandparent_stops_at_two_levels(self, mock_cache): + parent = MockFolder(pk=5, site_id=2) + child = MockFolder(pk=15, site_id=2, parent=parent) + invalidate_folder_listing_cache(child) + self.assertEqual(mock_cache.delete.call_count, 2) + + @patch('filer.utils.cache.cache') + def test_site_less_folder_with_parent(self, mock_cache): + """Folders with site_id=None format key with empty site.""" + parent = MockFolder(pk=1, site_id=None) + child = MockFolder(pk=2, site_id=None, parent=parent) + invalidate_folder_listing_cache(child) + mock_cache.delete.assert_has_calls([ + call(_key(None, 2)), + call(_key(None, 1)), + ]) + + @patch('filer.utils.cache.cache') + def test_mixed_site_ids_in_hierarchy(self, mock_cache): + """Each level uses its own site_id for the cache key.""" + grandparent = MockFolder(pk=1, site_id=10) + parent = MockFolder(pk=5, site_id=20, parent=grandparent) + child = MockFolder(pk=15, site_id=30, parent=parent) + invalidate_folder_listing_cache(child) + mock_cache.delete.assert_has_calls([ + call(_key(30, 15)), + call(_key(20, 5)), + call(_key(10, 1)), + ]) + + +class TestInvalidateFolderListingCacheForFile(TestCase): + + @patch('filer.utils.cache.cache') + def test_file_with_folder(self, mock_cache): + folder = MockFolder(pk=42, site_id=5) + file_obj = MockFile(folder=folder) + invalidate_folder_listing_cache_for_file(file_obj) + mock_cache.delete.assert_called_once_with(_key(5, 42)) + + @patch('filer.utils.cache.cache') + def test_file_without_folder_is_noop(self, mock_cache): + """Clipboard / unfiled files have folder=None.""" + file_obj = MockFile(folder=None) + invalidate_folder_listing_cache_for_file(file_obj) + mock_cache.delete.assert_not_called() + + @patch('filer.utils.cache.cache') + def test_file_in_nested_folder_invalidates_ancestors(self, mock_cache): + parent = MockFolder(pk=1, site_id=3) + folder = MockFolder(pk=10, site_id=3, parent=parent) + file_obj = MockFile(folder=folder) + invalidate_folder_listing_cache_for_file(file_obj) + mock_cache.delete.assert_has_calls([ + call(_key(3, 10)), + call(_key(3, 1)), + ]) + diff --git a/filer/tests/utils.py b/filer/tests/test_utils.py similarity index 72% rename from filer/tests/utils.py rename to filer/tests/test_utils.py index 7e10e6d5d..fe0a6b462 100644 --- a/filer/tests/utils.py +++ b/filer/tests/test_utils.py @@ -1,11 +1,13 @@ #-*- coding: utf-8 -*- +from zipfile import ZipFile +import os + from django.core.files import File as DjangoFile from django.test.testcases import TestCase from filer.tests.helpers import create_image -from filer.utils.loader import load + +from filer.utils.loader import load_object from filer.utils.zip import unzip -from zipfile import ZipFile -import os #=============================================================================== # Some target classes for the classloading tests @@ -20,20 +22,21 @@ class TestTargetClass(TestTargetSuperClass): # Testing the classloader #=============================================================================== class ClassLoaderTestCase(TestCase): - ''' Tests filer.utils.loader.load() ''' + ''' Tests filer.utils.loader.load_object() ''' def test_loader_loads_strings_properly(self): - target = 'filer.tests.utils.TestTargetClass' - result = load(target, None) # Should return an instance - self.assertEqual(result.__class__, TestTargetClass) + target = 'filer.tests.test_utils.TestTargetClass' + result = load_object(target) + self.assertEqual(result, TestTargetClass) - def test_loader_loads_class(self): - result = load(TestTargetClass(), TestTargetSuperClass) - self.assertEqual(result.__class__, TestTargetClass) + def test_loader_returns_non_string_as_is(self): + instance = TestTargetClass() + result = load_object(instance) + self.assertIs(result, instance) - def test_loader_loads_subclass(self): - result = load(TestTargetClass, TestTargetSuperClass) - self.assertEqual(result.__class__, TestTargetClass) + def test_loader_raises_on_no_dots(self): + with self.assertRaises(TypeError): + load_object('NoDots') #=============================================================================== # Testing the zipping/unzipping of files @@ -48,7 +51,7 @@ def setUp(self): self.image_name) self.img.save(self.filename, 'JPEG') - self.file = DjangoFile(open(self.filename), name=self.image_name) + self.file = DjangoFile(open(self.filename, 'rb'), name=self.image_name) self.zipfilename = 'test_zip.zip' diff --git a/filer/tests/tools.py b/filer/tests/tools.py index 1bbaa6f4f..6bcd0374e 100644 --- a/filer/tests/tools.py +++ b/filer/tests/tools.py @@ -1,5 +1,6 @@ #-*- coding: utf-8 -*- from django.core.files import File as DjangoFile +from django.http import HttpRequest from django.test.testcases import TestCase from filer.models import tools from filer.models.clipboardmodels import Clipboard @@ -18,7 +19,7 @@ def setUp(self): self.image_name) self.img.save(self.filename, 'JPEG') - self.file = DjangoFile(open(self.filename), name=self.image_name) + self.file = DjangoFile(open(self.filename, 'rb'), name=self.image_name) # This is actually a "file" for filer considerations self.image = Image.objects.create(owner=self.superuser, original_filename=self.image_name, @@ -32,8 +33,9 @@ def tearDown(self): self.client.logout() os.remove(self.filename) for img in Image.objects.all(): - os.remove(img.file.path) - img.delete() + img_path = img.file.path + img.delete(to_trash=False) + assert os.path.exists(img_path) == False def test_clear_clipboard_works(self): self.assertEqual(len(self.clipboard.files.all()), 1) @@ -50,14 +52,14 @@ def test_move_to_clipboard_works(self): original_filename='file3', file=self.file) files = [file2, file3] - - tools.move_file_to_clipboard(files, self.clipboard) + request = HttpRequest() + tools.move_file_to_clipboard(request, files, self.clipboard) self.assertEqual(len(self.clipboard.files.all()), 3) def test_move_from_clipboard_to_folder_works(self): self.assertEqual(len(self.clipboard.files.all()), 1) - - tools.move_files_from_clipboard_to_folder(self.clipboard, self.folder) + request = HttpRequest() + tools.move_files_from_clipboard_to_folder(request, self.clipboard, self.folder) for file in self.clipboard.files.all(): self.assertEqual(file.folder, self.folder) diff --git a/filer/tests/utils/__init__.py b/filer/tests/utils/__init__.py index 6cdab0a13..5776370aa 100644 --- a/filer/tests/utils/__init__.py +++ b/filer/tests/utils/__init__.py @@ -1,2 +1,31 @@ +from django.template.loaders.base import Loader as BaseLoader +from django.template import Origin +from django.template.exceptions import TemplateDoesNotExist + + class Mock(): pass + + +class MockLoader(BaseLoader): + + is_usable = True + + _templates = { + 'cms_mock_template.html': '

      ', + '404.html': '404 Not Found', + } + + def get_template_sources(self, template_name): + if template_name in self._templates: + yield Origin( + name=template_name, + template_name=template_name, + loader=self, + ) + + def get_contents(self, origin): + try: + return self._templates[origin.template_name] + except KeyError: + raise TemplateDoesNotExist(origin) diff --git a/filer/thumbnail_processors.py b/filer/thumbnail_processors.py index d448b94e8..04fc43789 100644 --- a/filer/thumbnail_processors.py +++ b/filer/thumbnail_processors.py @@ -1,23 +1,25 @@ -#-*- coding: utf-8 -*- import re + +from easy_thumbnails import processors + +from .settings import FILER_SUBJECT_LOCATION_IMAGE_DEBUG, FILER_WHITESPACE_COLOR + + try: - from PIL import Image - from PIL import ImageDraw + from PIL import Image, ImageDraw except ImportError: try: import Image import ImageDraw except ImportError: raise ImportError("The Python Imaging Library was not found.") -from easy_thumbnails import processors -from filer.settings import FILER_SUBJECT_LOCATION_IMAGE_DEBUG RE_SUBJECT_LOCATION = re.compile(r'^(\d+),(\d+)$') def normalize_subject_location(subject_location): if subject_location: - if isinstance(subject_location, basestring): + if isinstance(subject_location, str): m = RE_SUBJECT_LOCATION.match(subject_location) if m: return (int(m.group(1)), int(m.group(2))) @@ -30,12 +32,13 @@ def normalize_subject_location(subject_location): def scale_and_crop_with_subject_location(im, size, subject_location=False, - crop=False, upscale=False, **kwargs): + zoom=None, crop=False, upscale=False, + **kwargs): """ Like ``easy_thumbnails.processors.scale_and_crop``, but will use the coordinates in ``subject_location`` to make sure that that part of the image is in the center or at least somewhere on the cropped image. - Please not that this does *not* work correctly if the image has been + Please note that this does *not* work correctly if the image has been resized by a previous processor (e.g ``autocrop``). ``crop`` needs to be set for this to work, but any special cropping @@ -44,15 +47,15 @@ def scale_and_crop_with_subject_location(im, size, subject_location=False, subject_location = normalize_subject_location(subject_location) if not (subject_location and crop): # use the normal scale_and_crop - return processors.scale_and_crop(im, size, crop=crop, + return processors.scale_and_crop(im, size, zoom=zoom, crop=crop, upscale=upscale, **kwargs) # for here on we have a subject_location and cropping is on # --snip-- this is a copy and paste of the first few # lines of ``scale_and_crop`` - source_x, source_y = [float(v) for v in im.size] - target_x, target_y = [float(v) for v in size] + source_x, source_y = (float(v) for v in im.size) + target_x, target_y = (float(v) for v in size) if crop or not target_x or not target_y: scale = max(target_x / source_x, target_y / source_y) @@ -65,16 +68,27 @@ def scale_and_crop_with_subject_location(im, size, subject_location=False, elif not target_y: target_y = source_y * scale + if zoom: + if not crop: + target_x = round(source_x * scale) + target_y = round(source_y * scale) + scale *= (100 + int(zoom)) / 100.0 + if scale < 1.0 or (scale > 1.0 and upscale): - im = im.resize((int(source_x * scale), int(source_y * scale)), - resample=Image.ANTIALIAS) + try: + im = im.resize((int(source_x * scale), int(source_y * scale)), + resample=Image.LANCZOS) + except AttributeError: # pragma: no cover + im = im.resize((int(source_x * scale), int(source_y * scale)), + resample=Image.ANTIALIAS) + # --endsnip-- begin real code # =============================== # subject location aware cropping # =============================== # res_x, res_y: the resolution of the possibly already resized image - res_x, res_y = [float(v) for v in im.size] + res_x, res_y = (float(v) for v in im.size) # subj_x, subj_y: the position of the subject (maybe already re-scaled) subj_x = res_x * float(subject_location[0]) / source_x @@ -110,10 +124,37 @@ def scale_and_crop_with_subject_location(im, size, subject_location=False, if ex or ey: crop_box = ((int(tex), int(tey), int(tfx), int(tfy))) if FILER_SUBJECT_LOCATION_IMAGE_DEBUG: - # draw elipse on focal point for Debugging + # draw ellipse on focal point for Debugging draw = ImageDraw.Draw(im) esize = 10 draw.ellipse(((subj_x - esize, subj_y - esize), (subj_x + esize, subj_y + esize)), outline="#FF0000") im = im.crop(crop_box) return im + + +def whitespace(image, size, whitespace=False, whitespace_color=None, **kwargs): + if not whitespace: + return image + + if whitespace_color is None: + whitespace_color = FILER_WHITESPACE_COLOR + if whitespace_color is None: + whitespace_color = '#fff' + + old_image = image + source_x, source_y = image.size + target_x, target_y = size + + image = Image.new('RGBA', (target_x, target_y), whitespace_color) + if source_x < target_x and source_y < target_y: # whitespace all around + image.paste(old_image, ( + (target_x - source_x) / 2, (target_y - source_y) / 2)) + elif source_x < target_x: # whitespace on top and bottom only + image.paste(old_image, ((target_x - source_x) / 2, 0)) + elif source_y < target_y: # whitespace on sides only + image.paste(old_image, (0, (target_y - source_y) / 2)) + else: # no whitespace needed + image = old_image + + return image diff --git a/filer/urls.py b/filer/urls.py new file mode 100644 index 000000000..f8fccf4a1 --- /dev/null +++ b/filer/urls.py @@ -0,0 +1,13 @@ +from django.urls import path + +from . import settings as filer_settings +from . import views + + +urlpatterns = [ + path( + filer_settings.FILER_CANONICAL_URL + '//', + views.canonical, + name='canonical' + ), +] diff --git a/filer/utils/cache.py b/filer/utils/cache.py new file mode 100644 index 000000000..b9fa3ddb7 --- /dev/null +++ b/filer/utils/cache.py @@ -0,0 +1,70 @@ +#-*- coding: utf-8 -*- +""" +Cache invalidation utilities for filer folder listings. + +Invalidates the django_filer_rest folder-listing cache whenever +files or folders are added, moved, deleted, restored, or modified. +""" +import logging + +from django.conf import settings +from django.core.cache import cache + +logger = logging.getLogger(__name__) + +DEFAULT_FOLDER_LISTING_CACHE_KEY = 'django_filer_rest.folder-listing:{site_id}:{folder_id}' +FOLDER_LISTING_CACHE_KEY = getattr( + settings, 'FILER_FOLDER_LISTING_CACHE_KEY', DEFAULT_FOLDER_LISTING_CACHE_KEY) + + +def invalidate_folder_listing_cache(folder): + """ + Invalidate the folder-listing cache for the given folder, its parent, + and its grandparent. + + Args: + folder: A Folder model instance or a virtual folder (FolderRoot, + UnfiledImages). Virtual folders are ignored since they + have no cache key. + """ + if folder is None: + return + + # Virtual folders (FolderRoot, UnfiledImages) don't have pk/site_id + if not hasattr(folder, 'pk') or not folder.pk: + return + + site_id = folder.site_id if hasattr(folder, 'site_id') else None + + key = FOLDER_LISTING_CACHE_KEY.format( + site_id=site_id or '', folder_id=folder.pk) + cache.delete(key) + logger.debug("Cache invalidated: %s", key) + + # Also invalidate the parent folder (its child list changed) + parent = folder.parent if hasattr(folder, 'parent') else None + if parent: + parent_key = FOLDER_LISTING_CACHE_KEY.format( + site_id=parent.site_id or '', folder_id=parent.pk) + cache.delete(parent_key) + logger.debug("Cache invalidated (parent): %s", parent_key) + + # Also invalidate the grandparent folder + if parent.parent_id: + grandparent = parent.parent + gp_key = FOLDER_LISTING_CACHE_KEY.format( + site_id=grandparent.site_id or '', folder_id=grandparent.pk) + cache.delete(gp_key) + logger.debug("Cache invalidated (grandparent): %s", gp_key) + + +def invalidate_folder_listing_cache_for_file(file_obj): + """ + Invalidate the folder-listing cache for the folder containing this file. + + Args: + file_obj: A File model instance. + """ + if file_obj.folder: + invalidate_folder_listing_cache(file_obj.folder) + diff --git a/filer/utils/cdn.py b/filer/utils/cdn.py new file mode 100644 index 000000000..cd4086b3d --- /dev/null +++ b/filer/utils/cdn.py @@ -0,0 +1,42 @@ +import datetime +import urllib.parse + +from django.utils import timezone + +from filer import settings as filer_settings + + +def get_cdn_url(file_obj, url): + """If the CDN version of the file is up to date, return it from there""" + cdn_domain = getattr(filer_settings, 'CDN_DOMAIN', None) + if cdn_domain is None: + return url + + if file_obj.modified_at is None: + return url + + invalidated_at = file_obj.modified_at + datetime.timedelta( + seconds=filer_settings.CDN_INVALIDATION_TIME) + # django uses django.utils.timezone.now() to set value for + # modified_at field; + # it makes sense to use the same method to fetch current time; + now = timezone.now() + if timezone.is_naive(invalidated_at): + tz_used = timezone.get_default_timezone() + invalidated_at = timezone.make_aware(invalidated_at, tz_used) + else: + tz_used = invalidated_at.tzinfo + # since current time might have a timezone aware datetime(depending on + # django settings), make sure it will be converted to the same + # timezone as invalidated_at + if timezone.is_naive(now): + now = timezone.make_aware(now, tz_used) + else: + now = now.astimezone(tz_used) + + if invalidated_at < now: + scheme, netloc, path, params, query, fragment = urllib.parse.urlparse(url) + return urllib.parse.urlunparse( + (scheme, cdn_domain, path, params, query, fragment)) + else: + return url diff --git a/filer/utils/checktrees.py b/filer/utils/checktrees.py new file mode 100644 index 000000000..1a0b4ee0e --- /dev/null +++ b/filer/utils/checktrees.py @@ -0,0 +1,110 @@ +from django.db.models import Count + + +class TreeCorruption(Exception): + pass + + +class TreeChecker(object): + ordering = ['tree_id', 'lft', 'rght'] + + def __init__(self, folder_manager=None): + self.full_rebuild = False + self.corrupted_folders = {} + self.corruption_check_done = False + if not folder_manager: + from filer.models.foldermodels import Folder + self.manager = Folder._tree_manager + else: + self.manager = folder_manager + + def find_corruptions(self): + self.check_corruptions() + if (self.full_rebuild or self.corrupted_folders): + raise TreeCorruption() + + def _build_diff_msg(self, expected, actual): + attr_idx = {'lft': 0, 'rght': 1, 'level': 2, 'tree_id': 3} + expected, actual = list(expected), list(actual) + diff = [] + for attr, idx in list(attr_idx.items()): + if expected[idx] != actual[idx]: + diff.append('wrong %s value: expected %s, actual %s' % ( + attr, expected[idx], actual[idx])) + return '; '.join(diff) + + def _get_parents_names(self, folder, names): + names.insert(0, folder.name) + if folder.parent: + self._get_parents_names(folder.parent, names) + + def _get_folder_path(self, pk): + folder = self.manager.get(pk=pk) + names = [] + self._get_parents_names(folder, names) + return '/'.join(names) + + def get_corrupted_root_nodes(self): + if not self.corruption_check_done: + self.check_corruptions() + corrupted_trees = self.manager.filter( + pk__in=list(self.corrupted_folders.keys())). \ + values_list('tree_id', flat=True).distinct() + return self.manager.filter( + parent__isnull=True, deleted_at__isnull=True, tree_id__in=corrupted_trees) + + def check_tree(self, pk, lft, tree_id, level=0): + """ + * checks if a certain folder tree is corrupted or not. + * uses the same logic as django-mptt's rebuild tree + * ignores deleted folders, same as django-mptt's rebuild + """ + rght = lft + 1 + child_ids = self.manager.filter(parent__pk=pk). \ + order_by(*self.ordering).values_list('pk', flat=True) + + for child_id in child_ids: + rght = self.check_tree(child_id, rght, tree_id, level + 1) + + folder = self.manager.get(pk=pk) + if folder.deleted_at is None: + expected = (lft, rght, level, tree_id) + actual = (folder.lft, folder.rght, folder.level, folder.tree_id) + if expected != actual: + self.corrupted_folders.setdefault( + pk, self._build_diff_msg(expected, actual)) + return rght + 1 + + def check_corruptions(self): + """ + * checks folder tree corruptions + * based on django-mptt's rebuild method + * checks if there are multiple root folders with the + same tree id(fixing this will require a full rebuild) + """ + tree_duplicates = self.manager.filter(parent=None). \ + values_list('tree_id'). \ + annotate(count=Count('id')).filter(count__gt=1) + if len(tree_duplicates) > 0: + self.full_rebuild = True + self.corruption_check_done = True + return + + pks = self.manager.filter(parent=None). \ + order_by(*self.ordering).values_list('pk', flat=True) + idx = 0 + for pk in pks: + idx += 1 + self.check_tree(pk, 1, self.manager.get(pk=pk).tree_id) + + self.corruption_check_done = True + + def rebuild(self): + if not self.corruption_check_done: + self.check_corruptions() + + if self.full_rebuild: + self.manager.rebuild() + elif self.corrupted_folders: + for folder in self.get_corrupted_root_nodes(): + self.manager.partial_rebuild(folder.tree_id) diff --git a/filer/utils/cms_roles.py b/filer/utils/cms_roles.py new file mode 100644 index 000000000..cc43fa817 --- /dev/null +++ b/filer/utils/cms_roles.py @@ -0,0 +1,115 @@ +from functools import wraps + +from django.contrib.sites.models import Site +from django.core.exceptions import ImproperlyConfigured +from django.utils.module_loading import import_string + +from filer.settings import FILER_ROLES_MANAGER + + +class DefaultFilerRolesManager: + """Fallback roles manager used when cmsroles is not installed.""" + + def is_site_admin(self, user): + return user.is_superuser + + def has_perm_on_site(self, user, site_id, perm): + return user.has_perm(perm) + + def get_accessible_sites(self, user): + if user.is_superuser: + return set(Site.objects.values_list('id', flat=True)) + return set() + + def get_administered_sites(self, user): + if user.is_superuser: + return list(Site.objects.all()) + return [] + + +def get_roles_manager(): + if hasattr(get_roles_manager, '_cache'): + return get_roles_manager._cache + try: + if callable(FILER_ROLES_MANAGER): + manager = FILER_ROLES_MANAGER() + manager = import_string(FILER_ROLES_MANAGER)() + except ImportError: + err_msg = ("Cannot import {}! This should be a manager for permissions." + "Please consult documentation.".format(FILER_ROLES_MANAGER)) + raise ImproperlyConfigured(err_msg) + get_roles_manager._cache = manager + return manager + + +def get_or_fetch(fetch_func): + """ + Helper decorator that sets the result of the decorated function on + a user request object. It is used to minimise the number of queries done + per request. + """ + @wraps(fetch_func) + def wrapper(user, *args, **kwargs): + attr_name = '_%s' % fetch_func.__name__ + if not hasattr(user, attr_name): + result = fetch_func(user, *args, **kwargs) + setattr(user, attr_name, result) + return getattr(user, attr_name) + return wrapper + + +@get_or_fetch +def has_admin_role(user): + return get_roles_manager().is_site_admin(user) + + +def can_restrict_on_site(user, site): + site_id = site + if not str(site_id).isnumeric(): + site_id = getattr(site, 'id', None) + + def _fetch_perm_existance(): + manager = get_roles_manager() + return manager.has_perm_on_site(user, site_id, 'filer.can_restrict_operations') + + if user.is_superuser or (site_id is None and has_admin_role(user)): + return True + + if site_id: + if not hasattr(user, '_can_restrict_on_site'): + setattr(user, '_can_restrict_on_site', {}) + return user._can_restrict_on_site.setdefault( + site_id, _fetch_perm_existance()) + return False + + +def get_sites_without_restriction_perm(user): + if user.is_superuser: + return [] + return [site + for site in get_sites_for_user(user) + if can_restrict_on_site(user, site) is False] + + +@get_or_fetch +def get_admin_sites_for_user(user): + return get_roles_manager().get_administered_sites(user) + + +def has_role_on_site(user, site): + return user.is_superuser or site.id in get_sites_for_user(user) + + +def has_admin_role_on_site(user, site): + return site.id in [_site.id + for _site in get_admin_sites_for_user(user)] + + +@get_or_fetch +def get_sites_for_user(user): + """ + Returns all sites available for user. + """ + if user.is_superuser: + return set(Site.objects.values_list('id', flat=True)) + return get_roles_manager().get_accessible_sites(user) diff --git a/filer/utils/compatibility.py b/filer/utils/compatibility.py new file mode 100644 index 000000000..0c7fd5290 --- /dev/null +++ b/filer/utils/compatibility.py @@ -0,0 +1,33 @@ +from django.utils.functional import keep_lazy +from django.utils.text import Truncator, format_lazy + + +def string_concat(*strings): + return format_lazy('{}' * len(strings), *strings) + + +def truncate_words(s, num, end_text='...'): + # truncate_words was removed in Django 1.5. + truncate = end_text and ' %s' % end_text or '' + return Truncator(s).words(num, truncate=truncate) + + +truncate_words = keep_lazy(truncate_words, str) + + +def get_delete_permission(opts): + from django.contrib.auth import get_permission_codename + return '{}.{}'.format(opts.app_label, get_permission_codename('delete', opts)) + + +try: + from PIL import ExifTags as PILExifTags + from PIL import Image as PILImage + from PIL import ImageDraw as PILImageDraw +except ImportError: + try: + import ExifTags as PILExifTags # noqa + import Image as PILImage # noqa + import ImageDraw as PILImageDraw # noqa + except ImportError: + raise ImportError("The Python Imaging Library was not found.") diff --git a/filer/utils/filer_easy_thumbnails.py b/filer/utils/filer_easy_thumbnails.py index 29a16630b..00b2f4b43 100644 --- a/filer/utils/filer_easy_thumbnails.py +++ b/filer/utils/filer_easy_thumbnails.py @@ -1,8 +1,8 @@ -#-*- coding: utf-8 -*- -from easy_thumbnails.files import Thumbnailer import os import re -from filer import settings as filer_settings + +from easy_thumbnails.files import Thumbnailer + # match the source filename using `__` as the seperator. ``opts_and_ext`` is non # greedy so it should match the last occurence of `__`. @@ -18,7 +18,7 @@ def thumbnail_to_original_filename(thumbnail_name): return None -class ThumbnailerNameMixin(object): +class ThumbnailerNameMixin: thumbnail_basedir = '' thumbnail_subdir = '' thumbnail_prefix = '' @@ -30,7 +30,12 @@ def get_thumbnail_name(self, thumbnail_options, transparent=False): filename. """ path, source_filename = os.path.split(self.name) - if transparent: + source_extension = os.path.splitext(source_filename)[1][1:].lower() + preserve_extensions = self.thumbnail_preserve_extensions + if preserve_extensions is True or source_extension == 'svg' or \ + isinstance(preserve_extensions, (list, tuple)) and source_extension in preserve_extensions: + extension = source_extension + elif transparent: extension = self.thumbnail_transparency_extension else: extension = self.thumbnail_extension @@ -38,27 +43,31 @@ def get_thumbnail_name(self, thumbnail_options, transparent=False): thumbnail_options = thumbnail_options.copy() size = tuple(thumbnail_options.pop('size')) + initial_opts = ['{}x{}'.format(*size)] quality = thumbnail_options.pop('quality', self.thumbnail_quality) - initial_opts = ['%sx%s' % size, 'q%s' % quality] + if extension == 'jpg': + initial_opts.append(f'q{quality}') + elif extension == 'svg': + thumbnail_options.pop('subsampling', None) + thumbnail_options.pop('upscale', None) - opts = thumbnail_options.items() + opts = list(thumbnail_options.items()) opts.sort() # Sort the options so the file name is consistent. - opts = ['%s' % (v is not True and '%s-%s' % (k, v) or k) + opts = ['{}'.format(v is not True and f'{k}-{v}' or k) for k, v in opts if v] - all_opts = '_'.join(initial_opts + opts) basedir = self.thumbnail_basedir subdir = self.thumbnail_subdir - #make sure our magic delimiter is not used in all_opts + # make sure our magic delimiter is not used in all_opts all_opts = all_opts.replace('__', '_') - filename = u'%s__%s.%s' % (source_filename, all_opts, extension) + filename = f'{source_filename}__{all_opts}.{extension}' return os.path.join(basedir, path, subdir, filename) -class ActionThumbnailerMixin(object): +class ActionThumbnailerMixin: thumbnail_basedir = '' thumbnail_subdir = '' thumbnail_prefix = '' @@ -82,7 +91,7 @@ def thumbnail_exists(self, thumbnail_name): class FilerThumbnailer(ThumbnailerNameMixin, Thumbnailer): def __init__(self, *args, **kwargs): self.thumbnail_basedir = kwargs.pop('thumbnail_basedir', '') - super(FilerThumbnailer, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) class FilerActionThumbnailer(ActionThumbnailerMixin, Thumbnailer): diff --git a/filer/utils/files.py b/filer/utils/files.py index df1a739c2..07c3cb74f 100644 --- a/filer/utils/files.py +++ b/filer/utils/files.py @@ -1,8 +1,11 @@ -#-*- coding: utf-8 -*- +import mimetypes import os +import uuid + +from django.http.multipartparser import ChunkIter, SkipFile, StopFutureHandlers, StopUpload, exhaust +from django.template.defaultfilters import slugify as slugify_django +from django.utils.encoding import force_str from django.utils.text import get_valid_filename as get_valid_filename_django -from django.template.defaultfilters import slugify -from django.core.files.uploadedfile import SimpleUploadedFile class UploadException(Exception): @@ -10,33 +13,159 @@ class UploadException(Exception): def handle_upload(request): - if not request.method == "POST": - raise UploadException("AJAX request not valid: must be POST") - if request.is_ajax(): + if not request.method == 'POST': + raise UploadException("XMLHttpRequest not valid: must be POST") + if request.headers.get('x-requested-with') == 'XMLHttpRequest': # the file is stored raw in the request is_raw = True filename = request.GET.get('qqfile', False) or request.GET.get('filename', False) or '' - if hasattr(request, 'body'): - # raw_post_data was depreciated in django 1.4: - # https://docs.djangoproject.com/en/dev/releases/1.4/#httprequest-raw-post-data-renamed-to-httprequest-body - data = request.body + + try: + content_length = int(request.headers['content-length']) + except (IndexError, TypeError, ValueError): + content_length = None + + if content_length < 0: + # This means we shouldn't continue...raise an error. + raise UploadException("Invalid content length: %r" % content_length) + + mime_type = mimetypes.guess_type(filename)[0] or 'application/octet-stream' + + upload_handlers = request.upload_handlers + for handler in upload_handlers: + handler.handle_raw_input(request, + request.META, + content_length, + None, + None) + pass + + # For compatibility with low-level network APIs (with 32-bit integers), + # the chunk size should be < 2^31, but still divisible by 4. + possible_sizes = [x.chunk_size for x in upload_handlers if x.chunk_size] + chunk_size = min([2 ** 31 - 4] + possible_sizes) + + stream = ChunkIter(request, chunk_size) + counters = [0] * len(upload_handlers) + + try: + for handler in upload_handlers: + try: + handler.new_file(None, filename, + None, content_length, None) + except StopFutureHandlers: + break + + for chunk in stream: + for i, handler in enumerate(upload_handlers): + chunk_length = len(chunk) + chunk = handler.receive_data_chunk(chunk, + counters[i]) + counters[i] += chunk_length + if chunk is None: + # If the chunk received by the handler is None, then don't continue. + break + + except SkipFile: + # Just use up the rest of this file... + exhaust(stream) + except StopUpload as e: + if not e.connection_reset: + exhaust(request) else: - # fallback for django 1.3 - data = request.raw_post_data - upload = SimpleUploadedFile(name=filename, content=data) + # Make sure that the request data is all fed + exhaust(request) + + # Signal that the upload has completed. + for handler in upload_handlers: + retval = handler.upload_complete() + if retval: + break + + for i, handler in enumerate(upload_handlers): + file_obj = handler.file_complete(counters[i]) + if file_obj: + upload = file_obj + break else: if len(request.FILES) == 1: - # FILES is a dictionary in Django but Ajax Upload gives the uploaded file an - # ID based on a random number, so it cannot be guessed here in the code. - # Rather than editing Ajax Upload to pass the ID in the querystring, note that - # each upload is a separate request so FILES should only have one entry. - # Thus, we can just grab the first (and only) value in the dict. - is_raw = False - upload = request.FILES.values()[0] - filename = upload.name + upload, filename, is_raw, mime_type = handle_request_files_upload(request) + else: + raise UploadException("XMLHttpRequest request not valid: Bad Upload") + return upload, filename, is_raw, mime_type + + +def handle_request_files_upload(request): + """ + Handle request.FILES if len(request.FILES) == 1. + Returns tuple(upload, filename, is_raw, mime_type) where upload is file itself. + """ + # FILES is a dictionary in Django but Ajax Upload gives the uploaded file + # an ID based on a random number, so it cannot be guessed here in the code. + # Rather than editing Ajax Upload to pass the ID in the querystring, + # note that each upload is a separate request so FILES should only + # have one entry. + # Thus, we can just grab the first (and only) value in the dict. + is_raw = False + upload = list(request.FILES.values())[0] + filename = upload.name + _, iext = os.path.splitext(filename) + mime_type = upload.content_type.lower() + extensions = mimetypes.guess_all_extensions(mime_type) + if mime_type != 'application/octet-stream' and extensions and iext.lower() not in extensions: + # The browser's content type doesn't match the file extension. + # Check if the file extension has its own known MIME type (e.g. + # browser sends image/webp for a .jpg file, or application/x-zip-compressed + # for a .zip file). + guessed_type = mimetypes.guess_type(filename)[0] + if guessed_type: + # Extension has a known type – use it instead of rejecting. + mime_type = guessed_type + elif iext: + # Extension exists but is not recognized by Python's mimetypes + # (e.g. .jfif). Trust the browser's content type rather than + # rejecting the upload. + pass else: - raise UploadException("AJAX request not valid: Bad Upload") - return upload, filename, is_raw + # No file extension at all – trust the browser's content type. + pass + elif not extensions and mime_type != 'application/octet-stream': + # Browser sent an unrecognized MIME type; try to guess from filename + guessed_type = mimetypes.guess_type(filename)[0] + if guessed_type: + mime_type = guessed_type + return upload, filename, is_raw, mime_type + + +def slugify(string): + return slugify_django(force_str(string)) + + +def _ensure_safe_length(filename, max_length=155, random_suffix_length=16): + """ + Ensures that the filename does not exceed the maximum allowed length. + If it does, the function truncates the filename and appends a random hexadecimal + suffix of length `random_suffix_length` to ensure uniqueness and compliance with + database constraints - even after markers for a thumbnail are added. + + Parameters: + filename (str): The filename to check. + max_length (int): The maximum allowed length for the filename. + random_suffix_length (int): The length of the random suffix to append. + + Returns: + str: The safe filename. + + + Reference issue: https://github.com/django-cms/django-filer/issues/1270 + """ + + if len(filename) <= max_length: + return filename + + keep_length = max_length - random_suffix_length + random_suffix = uuid.uuid4().hex[:random_suffix_length] + return filename[:keep_length] + random_suffix def get_valid_filename(s): @@ -49,6 +178,58 @@ def get_valid_filename(s): filename = slugify(filename) ext = slugify(ext) if ext: - return u"%s.%s" % (filename, ext) + valid_filename = "{}.{}".format(filename, ext) + else: + valid_filename = "{}".format(filename) + + # Ensure the filename meets the maximum length requirements. + return _ensure_safe_length(valid_filename) + + +# PBS-specific: file type matching and filename utilities + +def matching_file_subtypes(filename, file_pointer, request): + """ + Returns a list of valid subtypes for a given file. + """ + from ..settings import FILER_FILE_MODELS + from .loader import load_model + + # If request/mime_type is None, try to guess from filename + mime_type = request + if mime_type is None and filename: + import mimetypes + mime_type = mimetypes.guess_type(filename)[0] + + types = [] + for model_path in FILER_FILE_MODELS: + types.append(load_model(model_path)) + + def _match_subtype(subtype): + return subtype.matches_file_type(filename, file_pointer, mime_type) + type_matches = list(filter(_match_subtype, types)) + return type_matches + + +def truncate_filename(upload, maxlen=None): + """ + Return truncated filename. + Pre-extension filename will be less than or equals maxlen (if passed). + """ + try: + import filetype as filetype_lib + except ImportError: + filetype_lib = None + + title, extension = os.path.splitext(upload.name) + if not extension.lstrip('.'): + guessed = '' + if filetype_lib is not None: + guessed = filetype_lib.guess_extension(upload) or '' + if hasattr(upload, 'seek'): + upload.seek(0) else: - return u"%s" % (filename,) + guessed = '' + filename = '{title}.{ext}'.format(title=title[:maxlen], + ext=extension.lstrip('.') or guessed) + return filename diff --git a/filer/utils/generate_filename.py b/filer/utils/generate_filename.py index 8d405f26a..5d107ce35 100644 --- a/filer/utils/generate_filename.py +++ b/filer/utils/generate_filename.py @@ -1,15 +1,28 @@ -from filer.utils.files import get_valid_filename -from django.utils.encoding import force_unicode, smart_str -import datetime import os +import uuid + +from django.core.exceptions import ObjectDoesNotExist +from django.core.files.uploadedfile import UploadedFile +from django.utils.encoding import force_str +from django.utils.timezone import now + +import filer + +from .files import get_valid_filename def by_date(instance, filename): - datepart = force_unicode(datetime.datetime.now().strftime(smart_str("%Y/%m/%d"))) + datepart = force_str(now().strftime("%Y/%m/%d")) return os.path.join(datepart, get_valid_filename(filename)) -class prefixed_factory(object): +def randomized(instance, filename): + uuid_str = str(uuid.uuid4()) + return os.path.join(uuid_str[0:2], uuid_str[2:4], uuid_str, + get_valid_filename(filename)) + + +class prefixed_factory: def __init__(self, upload_to, prefix): self.upload_to = upload_to self.prefix = prefix @@ -22,3 +35,42 @@ def __call__(self, instance, filename): if not self.prefix: return upload_to_str return os.path.join(self.prefix, upload_to_str) + + +# PBS-specific: path-based filename generation + +def _is_in_memory(file_): + return isinstance(file_, UploadedFile) + + +def _construct_logical_folder_path(filer_file): + return os.path.join(*(folder.name for folder in filer_file.logical_path)) + + +def _goes_to_clipboard(instance): + return instance.folder is None or ( + instance.pk is None and _is_in_memory(instance.file.file)) + + +def by_path(instance, filename): + if _goes_to_clipboard(instance): + from filer.models import Clipboard + try: + owner_name = instance.owner.username if instance.owner else '_missing_owner' + except (AttributeError, ObjectDoesNotExist): + owner_name = '_missing_owner' + return os.path.join( + Clipboard.folder_name, + owner_name, + filename) + else: + return os.path.join( + _construct_logical_folder_path(instance), + instance.actual_name) + + +def get_trash_path(instance): + path = [filer.settings.FILER_TRASH_PREFIX] + path.append("%s" % instance.pk) + path.append(instance.pretty_logical_path.strip('/')) + return os.path.join(*path) diff --git a/filer/utils/loader.py b/filer/utils/loader.py index 4c4d519c7..b75f8f4d6 100644 --- a/filer/utils/loader.py +++ b/filer/utils/loader.py @@ -1,4 +1,3 @@ -#-*- coding: utf-8 -*- """ This function is snatched from https://github.com/ojii/django-load/blob/3058ab9d9d4875589638cc45e84b59e7e1d7c9c3/django_load/core.py#L49 @@ -8,7 +7,8 @@ or method. """ -from django.utils.importlib import import_module + +from importlib import import_module def load_object(import_path): @@ -26,17 +26,24 @@ def load_object(import_path): If the attribute does not exist in the module, a AttributeError is raised. """ - if not isinstance(import_path, basestring): + if not isinstance(import_path, str): return import_path if '.' not in import_path: raise TypeError( - "'import_path' argument to 'django_load.core.load_object' " +\ - "must contain at least one dot.") + "'import_path' argument to 'django_load.core.load_object' must " + "contain at least one dot.") module_name, object_name = import_path.rsplit('.', 1) module = import_module(module_name) return getattr(module, object_name) +def load_model(model_name): + from django.apps import apps + + model_name_tuple = model_name.split('.') + return apps.get_model(*model_name_tuple) + + def storage_factory(klass, location, base_url): """ This factory returns an instance of the storage class provided. diff --git a/filer/utils/model_label.py b/filer/utils/model_label.py new file mode 100644 index 000000000..93cc66809 --- /dev/null +++ b/filer/utils/model_label.py @@ -0,0 +1,17 @@ +def get_model_label(model): + """ + Take a model class or model label and return its model label. + + >>> get_model_label(MyModel) + "myapp.MyModel" + + >>> get_model_label("myapp.MyModel") + "myapp.MyModel" + """ + if isinstance(model, str): + return model + else: + return "{}.{}".format( + model._meta.app_label, + model.__name__ + ) diff --git a/filer/utils/multi_model_qs.py b/filer/utils/multi_model_qs.py new file mode 100644 index 000000000..e87227ab5 --- /dev/null +++ b/filer/utils/multi_model_qs.py @@ -0,0 +1,49 @@ +from functools import reduce + + +class MultiMoldelQuerysetChain(object): + """ + Allows passing a list of different models querysets to a paginator without + transforming them into one list. + """ + + def __init__(self, qsets): + self._qsets = qsets + self._offsets = [] + offset = 0 + for q in qsets: + self._offsets.append(offset) + offset += q.count() + self.length = offset + + def __getitem__(self, key): + if isinstance(key, slice): + return self._get_slice(key) + elif isinstance(key, int): + return self._get_item(key) + else: + raise TypeError("QuerysetChain index must be int or slice not {}".format(type(key))) + + def _get_item(self, key): + if key < 0: + raise IndexError("index out of bounds {}".format(key)) + for index, offset in enumerate(self._offsets): + qset = self._qsets[index] + if key-offset < qset.count(): + return qset[key-offset] + raise IndexError("index out of bounds {}".format(key)) + + def _get_slice(self, key): + assert key.start is not None + assert key.stop is not None + assert key.step is None + slices = (self.slice(qs, key.start-offset, key.stop-offset) + for qs, offset in zip(self._qsets, self._offsets)) + return reduce(lambda s1, s2: s1+s2, slices) + + def slice(self, qset, start, stop): + start, stop = max(start, 0), max(stop, 0) + return list(qset[start:stop]) + + def __len__(self): + return self.length diff --git a/filer/utils/pil_exif.py b/filer/utils/pil_exif.py index a2e5eba04..f0280e4aa 100644 --- a/filer/utils/pil_exif.py +++ b/filer/utils/pil_exif.py @@ -1,35 +1,29 @@ -#-*- coding: utf-8 -*- -try: - from PIL import Image - from PIL import ExifTags -except ImportError: - try: - import Image - import ExifTags - except ImportError: - raise ImportError("The Python Imaging Library was not found.") +from django.core.files.storage import default_storage as storage + +from ..utils.compatibility import PILExifTags, PILImage def get_exif(im): try: exif_raw = im._getexif() or {} - except: + except Exception: + # Not available? Return empty dict return {} ret = {} - for tag, value in exif_raw.items(): - decoded = ExifTags.TAGS.get(tag, tag) + for tag, value in list(exif_raw.items()): + decoded = PILExifTags.TAGS.get(tag, tag) ret[decoded] = value return ret def get_exif_for_file(file_obj): - im = Image.open(file_obj, 'r') + im = PILImage.open(storage.open(file_obj.name), 'r') return get_exif(im) def get_subject_location(exif_data): try: r = (int(exif_data['SubjectLocation'][0]), int(exif_data['SubjectLocation'][1]),) - except: + except KeyError: r = None return r diff --git a/filer/utils/recursive_dictionary.py b/filer/utils/recursive_dictionary.py index fbabc74f6..01ad34be0 100644 --- a/filer/utils/recursive_dictionary.py +++ b/filer/utils/recursive_dictionary.py @@ -1,5 +1,3 @@ -#-*- coding: utf-8 -*- - # https://gist.github.com/114831 # recursive_dictionary.py # Created 2009-05-20 by Jannis Andrija Schnitzer. @@ -24,8 +22,10 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. + __author__ = 'jannis@itisme.org (Jannis Andrija Schnitzer)' + class RecursiveDictionary(dict): """RecursiveDictionary provides the methods rec_update and iter_rec_update that can be used to update member dictionaries rather than overwriting @@ -41,11 +41,11 @@ def rec_update(self, other, **third): {'foo': {'baz': 36, 'bar': 42}} """ try: - iterator = other.iteritems() + iterator = other.items() except AttributeError: iterator = other self.iter_rec_update(iterator) - self.iter_rec_update(third.iteritems()) + self.iter_rec_update(third.items()) def iter_rec_update(self, iterator): for (key, value) in iterator: @@ -65,7 +65,7 @@ class RecursiveDictionaryWithExcludes(RecursiveDictionary): """ def __init__(self, *args, **kwargs): self.rec_excluded_keys = kwargs.pop('rec_excluded_keys', ()) - super(RecursiveDictionaryWithExcludes, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def iter_rec_update(self, iterator): for (key, value) in iterator: @@ -76,4 +76,4 @@ def iter_rec_update(self, iterator): rec_excluded_keys=self.rec_excluded_keys) self[key].rec_update(value) else: - self[key] = value \ No newline at end of file + self[key] = value diff --git a/filer/utils/status.py b/filer/utils/status.py new file mode 100644 index 000000000..936dd9d53 --- /dev/null +++ b/filer/utils/status.py @@ -0,0 +1,163 @@ +import gc +import requests +from collections import defaultdict + + +from filer.models import File, Folder + + +def chunked_items(qs, size=100): + pk = 0 + last_pk = qs.order_by('-pk')[0].pk + queryset = qs.order_by('pk') + while pk < last_pk: + for row in queryset.filter(pk__gt=pk)[:size]: + pk = row.pk + yield row + gc.collect() + + +class FileStats(object): + + def __init__(self, total): + self.private = defaultdict(list) + self.private.setdefault('total' , 0) + self.public = defaultdict(list) + self.public.setdefault('total' , 0) + + self.current_item = None + self.current_stats = None + self.index = 0 + self.total = total + + def set_current(self, asset, public=True): + self.current_item = asset + self.current_stats = self.public if public else self.private + self.current_stats['total'] += 1 + self.index += 1 + + def mark_current(self, marker): + self.current_stats[marker].append(self.current_item) + + def progress(self): + return "Checked {current} of {total} files".format( + current=self.index, total=self.total) + + def summary(self): + data = { + "total_checked": self.index, + "total_initial": self.total, + "total_private": self.private['total'], + "total_public": self.public['total'], + } + for prefix in ('public', 'private'): + data.update({ + "{prefix}_{marker}".format(prefix=prefix, marker=k): len(v) + for k, v in list(getattr(self, prefix).items()) + if k != 'total' + }) + return data + + def full_summary(self): + data = self.summary() + for prefix in ('public', 'private'): + data.update({ + "{prefix}_{marker}".format(prefix=prefix, marker=k): v + for k, v in list(getattr(self, prefix).items()) + if k != 'total' + }) + for prefix in ('public', 'private'): + data.update({ + "Total {prefix}_{marker}".format(prefix=prefix, marker=k): len(v) + for k, v in list(getattr(self, prefix).items()) + if k != 'total' + }) + + return data + + def as_string(self, full=False): + to_title = lambda x: x.capitalize().replace('_', ' ') + join = lambda x: '\n\t' + '\n\t'.join(x) + + data = self.full_summary() if full else self.summary() + return '\n'.join(sorted([ + "%s %s" % (to_title(k), join(v) if hasattr(v, '__iter__') else v) + for k, v in list(data.items())])) + + +class FileChecker(object): + + def __init__(self, filer_file): + self._file = filer_file + self._logical_path = '' + + @property + def storage(self): + return self._file.file.storage + + @property + def file_path(self): + return self._file.file.name + + @property + def logical_path(self): + if not self._logical_path: + self._logical_path = self._file.pretty_logical_path + return self._logical_path + + def exists(self): + return self.storage.exists(self.file_path) + + def path_logical(self): + return self.file_path.endswith(self.logical_path) + + def accessible(self): + try: + response = requests.head(self._file.url) + except requests.exceptions.RequestException as exc: + return False + return response.status_code == requests.codes.ok + + def as_string(self): + return "%s: %s" % (self._file.pk, self.logical_path, ) + + @classmethod + def check_all(cls, log_progress=None): + stats = FileStats(File.objects.count()) + log_progress = log_progress or (lambda x: None) + + for _file in chunked_items(File.objects.all()): + asset = cls(_file) + stats.set_current(asset.as_string(), _file.is_public) + + if not asset.path_logical(): + stats.mark_current('path_mismatch') + if not asset.accessible(): + stats.mark_current('not_accessible') + if not asset.exists(): + stats.mark_current('missing') + log_progress(stats) + + return stats + + @classmethod + def check_site(cls, site_id, log_progress=None): + folders = Folder.objects.filter(site_id=site_id).values_list('pk', flat=True) + files = File.objects.filter(folder_id__in=folders) + + stats = FileStats(files.count()) + log_progress = log_progress or (lambda x: None) + + for _file in chunked_items(files): + asset = cls(_file) + stats.set_current(f'{asset.as_string()} \nurl:{str(_file.file)}', _file.is_public) + + if not asset.path_logical(): + stats.mark_current('path_mismatch') + if not asset.accessible(): + stats.mark_current('not_accessible') + if not asset.exists(): + stats.mark_current('missing') + log_progress(stats) + + return stats diff --git a/filer/validation.py b/filer/validation.py new file mode 100644 index 000000000..4a34d85d1 --- /dev/null +++ b/filer/validation.py @@ -0,0 +1,115 @@ +import typing + +from django.apps import apps +from django.contrib.auth import get_user_model +from django.core.exceptions import ValidationError +from django.utils.translation import gettext as _ + + +User = get_user_model() # Needed for typing + + +class FileValidationError(ValidationError): + pass + + +def deny(file_name: str, file: typing.IO, owner: User, mime_type: str) -> None: + file_type = file_name.rsplit(".")[-1] + if file_type == file_name: + raise FileValidationError( + _('File "{file_name}": Upload denied by site security policy').format(file_name=file_name) + ) + raise FileValidationError( + _('File "{file_name}": {file_type} upload denied by site security policy').format( + file_name=file_name, + file_type=file_type.upper() + ) + ) + + +def deny_html(file_name: str, file: typing.IO, owner: User, mime_type: str) -> None: + """Simple validator that denies all files. Separate for HTML since .html and .htm are both + common suffixes for text/html files.""" + raise FileValidationError( + _('File "{file_name}": HTML upload denied by site security policy').format(file_name=file_name) + ) + + +TRIGGER_XSS_THREAD = ( + # Part 1: Event attributes that take js code as values + # See https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/Events + b"onbegin=", b"onend=", b"onrepeat=", + b"onabort=", b"onerror=", b"onresize=", b"onscroll=", b"onunload=", + b"oncopy=", b"oncut=", b"onpaste=", + b"oncancel=", b"oncanplay=", b"oncanplaythrough=", b"onchange=", b"onclick=", b"onclose=", b"oncuechange=", b"ondblclick=", + b"ondrag=", b"ondragend=", b"ondragenter=", b"ondragleave=", b"ondragover=", b"ondragstart=", b"ondrop=", + b"ondurationchange=", b"onemptied=", b"onended=", b"onerror=", b"onfocus=", b"oninput=", b"oninvalid=", + b"onkeydown=", b"onkeypress=", b"onkeyup=", b"onload=", b"onloadeddata=", b"onloadedmetadata=", b"onloadstart=", + b"onmousedown=", b"onmouseenter=", b"onmouseleave=", b"onmousemove=", b"onmouseout=", b"onmouseover=", b"onmouseup=", + b"onmousewheel=", b"onpause=", b"onplay=", b"onplaying=", b"onprogress=", b"onratechange=", b"onreset=", b"onresize=", + b"onscroll=", b"onseeked=", b"onseeking=", b"onselect=", b"onshow=", b"onstalled=", b"onsubmit=", b"onsuspend=", + b"ontimeupdate=", b"ontoggle==", b"onvolumechange==", b"onwaiting=", + b"onactivate=", b"onfocusin=", b"onfocusout=", +) + ( + # Part 2: + # Reject base64 obfuscated content + b";base64,", +) + ( + # Part 3: Obvious scripts + # Reject direct tags or javascript: uri + b" None: + """SVG files must not contain script tags or javascript hrefs. + This might be too strict but avoids parsing the xml""" + content = file.read().lower() + if any(map(lambda x: x in content, TRIGGER_XSS_THREAD)): + # If any element of TRIGGER_XSS_THREAD is found in file, raise FileValidationError + raise FileValidationError( + _('File "{file_name}": Rejected due to potential cross site scripting vulnerability') + .format(file_name=file_name) + ) + + +def sanitize_svg(file_name: str, file: typing.IO, owner: User, mime_type: str) -> None: + from easy_thumbnails.VIL.Image import Image + from reportlab.graphics import renderSVG + from svglib.svglib import svg2rlg + drawing = svg2rlg(file) + if not drawing: + raise FileValidationError( + _('File "{file_name}": SVG file format not recognized') + .format(file_name=file_name) + ) + image = Image(size=(drawing.width, drawing.height)) + renderSVG.draw(drawing, image.canvas) + xml = image.canvas.svg.toxml(encoding="UTF-8") # Removes non-graphic nodes -> sanitation + file.seek(0) # Rewind file + file.write(xml) # write to binary file with utf-8 encoding + + +def validate_upload(file_name: str, file: typing.IO, owner: User, mime_type: str) -> None: + """Actual validation: Call all validators for the given mime type. The app config reads + the validators from the settings and replaces dotted paths by callables.""" + + config = apps.get_app_config("filer") + + # First, check white list if provided + if config.MIME_TYPE_WHITELIST: + # FILER_MIME_TYPE_WHITELIST restricts the allowed mime types to, e.g., "image/*" or "text/plain" + for allowed_mime_type in config.MIME_TYPE_WHITELIST: + if mime_type == allowed_mime_type: + break + elif "/" in allowed_mime_type and [mime_type.split("/")[0], "*"] == allowed_mime_type.split("/", 1): + break + else: + # No match found <=> no break in for loop? Deny file + deny(file_name, file, owner, mime_type) + + # Second, check upload validators + if mime_type in config.FILE_VALIDATORS: + for validator in config.FILE_VALIDATORS[mime_type]: + validator(file_name, file, owner, mime_type) diff --git a/filer/views.py b/filer/views.py index e03cdc818..8e23fe03b 100755 --- a/filer/views.py +++ b/filer/views.py @@ -1,32 +1,16 @@ -#-*- coding: utf-8 -*- -from django import forms -from django.contrib.admin import widgets -from django.contrib.auth.decorators import login_required -from django.core.exceptions import PermissionDenied -from django.http import HttpResponseRedirect, HttpResponse -from django.shortcuts import render_to_response -from django.template import RequestContext -from django.utils.translation import ugettext_lazy as _ -from models import Folder, Image, Clipboard, tools, FolderRoot -from filer import settings as filer_settings - - -class NewFolderForm(forms.ModelForm): - class Meta: - model = Folder - fields = ('name',) - widgets = { - 'name': widgets.AdminTextInputWidget, - } +from django.http import Http404 +from django.shortcuts import get_object_or_404, redirect +# --- PBS-specific view helpers --- def popup_status(request): - return ('_popup' in request.REQUEST or 'pop' in request.REQUEST) + return ('_popup' in request.GET or '_popup' in request.POST + or 'pop' in request.GET or 'pop' in request.POST) def selectfolder_status(request): - return ('select_folder' in request.REQUEST) + return 'select_folder' in request.GET or 'select_folder' in request.POST def popup_param(request, separator="?"): @@ -35,6 +19,7 @@ def popup_param(request, separator="?"): else: return "" + def selectfolder_param(request, separator="&"): if selectfolder_status(request): return "%sselect_folder=1" % separator @@ -42,140 +27,32 @@ def selectfolder_param(request, separator="&"): return "" -def _userperms(item, request): - r = [] - ps = ['read', 'edit', 'add_children'] - for p in ps: - attr = "has_%s_permission" % p - if hasattr(item, attr): - x = getattr(item, attr)(request) - if x: - r.append(p) - return r - - -@login_required -def edit_folder(request, folder_id): - # TODO: implement edit_folder view - folder = None - return render_to_response('admin/filer/folder/folder_edit.html', { - 'folder': folder, - 'is_popup': popup_status(request), - 'select_folder': selectfolder_status(request), - }, context_instance=RequestContext(request)) - - -@login_required -def edit_image(request, folder_id): - # TODO: implement edit_image view - folder = None - return render_to_response('filer/image_edit.html', { - 'folder': folder, - 'is_popup': popup_status(request), - 'select_folder': selectfolder_status(request), - }, context_instance=RequestContext(request)) - - -@login_required -def make_folder(request, folder_id=None): - if not folder_id: - folder_id = request.REQUEST.get('parent_id', None) - if folder_id: - folder = Folder.objects.get(id=folder_id) - else: - folder = None - - if request.user.is_superuser: - pass - elif folder == None: - # regular users may not add root folders unless configured otherwise - if not filer_settings.FILER_ALLOW_REGULAR_USERS_TO_ADD_ROOT_FOLDERS: - raise PermissionDenied - elif not folder.has_add_children_permission(request): - # the user does not have the permission to add subfolders - raise PermissionDenied - - if request.method == 'POST': - new_folder_form = NewFolderForm(request.POST) - if new_folder_form.is_valid(): - new_folder = new_folder_form.save(commit=False) - if (folder or FolderRoot()).contains_folder(new_folder.name): - new_folder_form._errors['name'] = new_folder_form.error_class([_('Folder with this name already exists.')]) - else: - new_folder.parent = folder - new_folder.owner = request.user - new_folder.save() - return HttpResponse('') - else: - new_folder_form = NewFolderForm() - return render_to_response('admin/filer/folder/new_folder_form.html', { - 'new_folder_form': new_folder_form, - 'is_popup': popup_status(request), - 'select_folder': selectfolder_status(request), - }, context_instance=RequestContext(request)) - - -class UploadFileForm(forms.ModelForm): - class Meta: - model = Image - - -@login_required -def upload(request): - return render_to_response('filer/upload.html', { - 'title': u'Upload files', - 'is_popup': popup_status(request), - 'select_folder': selectfolder_status(request), - }, context_instance=RequestContext(request)) - - -@login_required -def paste_clipboard_to_folder(request): - if request.method == 'POST': - folder = Folder.objects.get(id=request.POST.get('folder_id')) - clipboard = Clipboard.objects.get(id=request.POST.get('clipboard_id')) - if folder.has_add_children_permission(request): - tools.move_files_from_clipboard_to_folder(clipboard, folder) - tools.discard_clipboard(clipboard) - else: - raise PermissionDenied - return HttpResponseRedirect('%s%s%s' % ( - request.REQUEST.get('redirect_to', ''), - popup_param(request), - selectfolder_param(request))) - - -@login_required -def discard_clipboard(request): - if request.method == 'POST': - clipboard = Clipboard.objects.get(id=request.POST.get('clipboard_id')) - tools.discard_clipboard(clipboard) - return HttpResponseRedirect('%s%s%s' % ( - request.POST.get('redirect_to', ''), - popup_param(request), - selectfolder_param(request))) - - -@login_required -def delete_clipboard(request): - if request.method == 'POST': - clipboard = Clipboard.objects.get(id=request.POST.get('clipboard_id')) - tools.delete_clipboard(clipboard) - return HttpResponseRedirect('%s%s%s' % ( - request.POST.get('redirect_to', ''), - popup_param(request), - selectfolder_param(request))) - - -@login_required -def clone_files_from_clipboard_to_folder(request): - if request.method == 'POST': - clipboard = Clipboard.objects.get(id=request.POST.get('clipboard_id')) - folder = Folder.objects.get(id=request.POST.get('folder_id')) - tools.clone_files_from_clipboard_to_folder(clipboard, folder) - return HttpResponseRedirect('%s%s%s' % ( - request.POST.get('redirect_to', ''), - popup_param(request), - selectfolder_param(request))) +def current_site_param(request, separator="&"): + current_site = get_param_from_request(request, 'current_site') + if current_site: + return '%scurrent_site=%s' % (separator, current_site) + return "" + + +def file_type_param(request, separator="&"): + param = get_param_from_request(request, 'file_type') + if param: + return '%sfile_type=%s' % (separator, param) + return "" + + +def get_param_from_request(request, param, default=None): + return request.POST.get(param) or request.GET.get(param) or default + + +# --- Upstream canonical view --- + +def canonical(request, uploaded_at, file_id): + """ + Redirect to the current url of a public file + """ + from .models import File + filer_file = get_object_or_404(File, pk=file_id, is_public=True) + if (not filer_file.file or int(uploaded_at) != filer_file.canonical_time): + raise Http404('No %s matches the given query.' % File._meta.object_name) + return redirect(filer_file.url) diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..30d500838 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1492 @@ +{ + "name": "django-filer", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "django-filer", + "version": "1.0.0", + "dependencies": { + "dropzone": "^5.9.3", + "mediator-js": "^0.11.0" + }, + "devDependencies": { + "webpack": "^5.90.0", + "webpack-cli": "^5.1.4" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "25.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.1.tgz", + "integrity": "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": ">=7.24.0 <7.24.7" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", + "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", + "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", + "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "acorn": "^8.14.0" + } + }, + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.32", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.32.tgz", + "integrity": "sha512-wbPvpyjJPC0zdfdKXxqEL3Ea+bOMD/87X4lftiJkkaBiuG6ALQy1SLmEd7BSmVCuwCQsBrCamgBoLyfFDD1EPg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/browserslist": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001793", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz", + "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/dropzone": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/dropzone/-/dropzone-5.9.3.tgz", + "integrity": "sha512-Azk8kD/2/nJIuVPK+zQ9sjKMRIpRvNyqn9XwbBHNq+iNuSccbJS6hwm1Woy0pMST0erSo0u4j+KJaodndDk4vA==", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.363", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.363.tgz", + "integrity": "sha512-VjUKPyWzGnT1fujlkEGC/BvN70Hh70KXtAqcmniXviYlJC/ivcT+BWGPyxWVbJZLfvtKR6dqg1L7T7pgAMBtWA==", + "dev": true, + "license": "ISC" + }, + "node_modules/enhanced-resolve": { + "version": "5.22.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.22.0.tgz", + "integrity": "sha512-xYcDWrpELkFzz9SpZ3PlI6Eu6eD93Yf0WLDRxikGhWJ3MAir2SNZTIVCVZqZ/NUyx8AdMc2gT9C0gPiw18kG+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/envinfo": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.21.0.tgz", + "integrity": "sha512-Lw7I8Zp5YKHFCXL7+Dz95g4CcbMEpgvqZNNq3AmlT5XAV6CgAAk6gyAMqn2zjw08K9BHfcNuKrMiCPLByGafow==", + "dev": true, + "license": "MIT", + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/hasown": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", + "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/loader-runner": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz", + "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mediator-js": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/mediator-js/-/mediator-js-0.11.0.tgz", + "integrity": "sha512-ehVcM3bSkr79E5yXUIyOPxw9xqhmvtTMkws5+lT8vl52awVkL/8rfDd8njmVxNldGmqKvFWSOvfppxG2AHM0TQ==", + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.46", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.46.tgz", + "integrity": "sha512-GYVXHE2KnrzAfsAjl4uP++evGFCrAU1jta4ubEjIG7YWt/64Gqv66a30yKwWczVjA6j3bM4nBwH7Pk1JmDHaxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/schema-utils": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", + "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser": { + "version": "5.48.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.48.0.tgz", + "integrity": "sha512-J/9An6vs9Us6wKRriSFXBWdRZapREHqFzdNUKk0pmu804EMR6dr6winwo7e5JDxN4xahxQsuysyYFwlwj4XN/Q==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.6.1.tgz", + "integrity": "sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "terser": "^5.31.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@minify-html/node": { + "optional": true + }, + "@swc/core": { + "optional": true + }, + "@swc/css": { + "optional": true + }, + "@swc/html": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "cssnano": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "html-minifier-terser": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "postcss": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/undici-types": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", + "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", + "dev": true, + "license": "MIT" + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/watchpack": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", + "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack": { + "version": "5.107.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.107.2.tgz", + "integrity": "sha512-v7RhXaJbpMlV0D7hC7lb2EbnxkoeUqf9qhKr6lozx3Q48pmFrqqNRmZFUEGmi7pSwm6fCQ2H1IjvCkHqdpVdjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.16.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.28.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.22.0", + "es-module-lexer": "^2.1.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "loader-runner": "^4.3.2", + "mime-db": "^1.54.0", + "neo-async": "^2.6.2", + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "terser-webpack-plugin": "^5.5.0", + "watchpack": "^2.5.1", + "webpack-sources": "^3.5.0" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-cli": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", + "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^2.1.1", + "@webpack-cli/info": "^2.0.2", + "@webpack-cli/serve": "^2.0.5", + "colorette": "^2.0.14", + "commander": "^10.0.1", + "cross-spawn": "^7.0.3", + "envinfo": "^7.7.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.5.0.tgz", + "integrity": "sha512-HPuy+uuoTCaaoEoI1LQ3JN9+vrPBvEesnnX1jADHy728cHSMlq4wUc4afYqahq2B1mhQVZxCXOkNTnXltr+2vQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 000000000..e151a660a --- /dev/null +++ b/package.json @@ -0,0 +1,18 @@ +{ + "name": "django-filer", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "webpack --mode production", + "build:dev": "webpack --mode development" + }, + "devDependencies": { + "webpack": "^5.90.0", + "webpack-cli": "^5.1.4" + }, + "dependencies": { + "dropzone": "^5.9.3", + "mediator-js": "^0.11.0" + } +} + diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..e134e5911 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,109 @@ +[build-system] +requires = ["setuptools>=45", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "django-filer" +dynamic = ["version"] +authors = [ + {name = "Divio AG", email = "info@divio.ch"}, +] +maintainers = [ + {name = "Django CMS Association and contributors", email = "info@django-cms.org"}, + {name = "PBS"}, +] +description = "A file management application for django that makes handling of files and images a breeze." +readme = "README.rst" +license = {text = "BSD-3-Clause"} +requires-python = ">=3.10" +dependencies = [ + "django>=5.1,<5.2", + "django-mptt>=0.6,<1.0", + "django-polymorphic>=4.0.0,<5.0", + "django-js-asset>=2.0.0,<3.0", + "easy-thumbnails[svg]>=2,<3.0", + "Unidecode>=0.04,<1.2", + "filetype", + "pytz", + + # Pin svglib to a version below 1.6.0. + # The latest version (1.6.0) adds pycairo as a dependency, + # which requires system-level libraries and fails to install in the container. + # This can be removed once the issue is resolved. + # See: https://github.com/deeplook/svglib/issues/421 + "svglib~=1.5.1", +] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Environment :: Web Environment", + "Intended Audience :: Developers", + "License :: OSI Approved :: BSD License", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Framework :: Django", + "Framework :: Django :: 5.1", + "Topic :: Internet :: WWW/HTTP", + "Topic :: Internet :: WWW/HTTP :: Dynamic Content", + "Topic :: Software Development", + "Topic :: Software Development :: Libraries", +] + +[project.optional-dependencies] +s3 = [ + "boto3>=1.26,<2.0", + "django-storages>=1.13,<2.0", +] +heif = ["pillow-heif"] + +[project.urls] +Homepage = "https://github.com/pbs/django-filer" + +[tool.setuptools] +include-package-data = true +zip-safe = false + +[tool.setuptools.packages.find] +where = ["."] +include = ["filer*", "LICENSE"] + +[tool.setuptools.package-data] +"*" = [ + "templates/**/*.html", + "static/**/*", + "locale/**/*", + "*.po", + "*.mo", +] + +[tool.setuptools.dynamic] +version = {attr = "filer.__version__"} + +[tool.flake8] +max-line-length = 119 +exclude = [ + "*.egg-info", + ".eggs", + ".env", + ".git", + ".settings", + ".tox", + ".venv", + "build", + "data", + "dist", + "docs", + "*migrations*", + "tmp", + "node_modules", +] +ignore = ["E251", "E128", "E501", "W503"] + +[tool.ruff] +src = ["filer"] +exclude = ["*/migrations/*"] +line-length = 119 diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 000000000..1ddb7e95a --- /dev/null +++ b/pytest.ini @@ -0,0 +1,6 @@ +[pytest] +python_files = *.py +python_classes = Test* *Tests *TestCase +python_functions = test_* +testpaths = filer/tests + diff --git a/setup.py b/setup.py deleted file mode 100644 index 324851ba9..000000000 --- a/setup.py +++ /dev/null @@ -1,49 +0,0 @@ -from setuptools import setup, find_packages -import os - -try: - from setuptest import test -except ImportError: - from setuptools.command.test import test - -version = __import__('filer').__version__ - -def read(fname): - # read the contents of a text file - return open(os.path.join(os.path.dirname(__file__), fname)).read() - -setup( - name = "django-filer", - version = version, - url = 'http://github.com/stefanfoulis/django-filer', - license = 'BSD', - platforms=['OS Independent'], - description = "A file management application for django that makes handling of files and images a breeze.", - long_description = read('README.rst'), - author = 'Stefan Foulis', - author_email = 'stefan.foulis@gmail.com', - packages=find_packages(), - install_requires = ( - 'Django>=1.3,<1.5', - 'easy-thumbnails>=1.0', - 'django-mptt>=0.5.1,<0.6', - 'django_polymorphic>=0.2', - ), - include_package_data=True, - zip_safe=False, - classifiers = [ - 'Development Status :: 4 - Beta', - 'Framework :: Django', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: BSD License', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Topic :: Internet :: WWW/HTTP', - ], - cmdclass={'test': test}, - test_suite='setuptest.setuptest.SetupTestSuite', - tests_require=( - 'django-setuptest>=0.1.1', - 'argparse', # apparently needed by django-setuptest on python 2.6 - ), -) diff --git a/test_image_upload.py b/test_image_upload.py new file mode 100644 index 000000000..0c1f4cdac --- /dev/null +++ b/test_image_upload.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +"""Test uploading images through the full ajax_upload flow to find what fails.""" +import os +os.environ['DJANGO_SETTINGS_MODULE'] = 'test_settings' +import django; django.setup() +from django.conf import settings; settings.ALLOWED_HOSTS = ['*'] + +from django.core.management import call_command +call_command('migrate', '--run-syncdb', verbosity=0) + +from django.contrib.auth.models import User +from django.core.files.uploadedfile import SimpleUploadedFile +from django.test.client import Client +from django.urls import reverse +from filer.models.filemodels import File +from filer.models.foldermodels import Folder +from filer.models.clipboardmodels import Clipboard, ClipboardItem +from PIL import Image as PILImage +import io, json + +user = User.objects.filter(username='imgtest').first() +if not user: + user = User.objects.create_superuser('imgtest', 'a@a.com', 'secret') + +folder, _ = Folder.objects.get_or_create(name='img_test', owner=user) + +client = Client() +client.login(username='imgtest', password='secret') + +def test_upload(name, data, content_type): + """Test uploading through ajax_upload endpoint.""" + ClipboardItem.objects.filter(clipboard__user=user).delete() + upload = SimpleUploadedFile(name, data, content_type=content_type) + url = reverse('admin:filer-ajax_upload', kwargs={'folder_id': folder.pk}) + response = client.post(url, {'file': upload}) + result = json.loads(response.content.decode()) + success = 'file_id' in result + return success, result + +# Test 1: Normal JPEG +print("=" * 60) +print("Test 1: Standard JPEG image") +buf = io.BytesIO() +img = PILImage.new('RGB', (800, 600), color='red') +img.save(buf, format='JPEG') +ok, res = test_upload('test1.jpg', buf.getvalue(), 'image/jpeg') +print(f" Result: {'PASS' if ok else 'FAIL'} - {res}") + +# Test 2: WebP image saved as .jpg +print("\nTest 2: WebP image saved with .jpg extension") +buf = io.BytesIO() +img = PILImage.new('RGB', (800, 600), color='blue') +img.save(buf, format='WEBP') +ok, res = test_upload('test2.jpg', buf.getvalue(), 'image/webp') +print(f" Result: {'PASS' if ok else 'FAIL'} - {res}") + +# Test 3: WebP image with .webp extension +print("\nTest 3: WebP image with proper .webp extension") +buf = io.BytesIO() +img = PILImage.new('RGB', (800, 600), color='green') +img.save(buf, format='WEBP') +ok, res = test_upload('test3.webp', buf.getvalue(), 'image/webp') +print(f" Result: {'PASS' if ok else 'FAIL'} - {res}") + +# Test 4: JPEG image with no extension +print("\nTest 4: JPEG image with no extension") +buf = io.BytesIO() +img = PILImage.new('RGB', (800, 600), color='yellow') +img.save(buf, format='JPEG') +ok, res = test_upload('image_no_ext', buf.getvalue(), 'image/jpeg') +print(f" Result: {'PASS' if ok else 'FAIL'} - {res}") + +# Test 5: Large JPEG image (high resolution) +print("\nTest 5: Large JPEG (4000x3000)") +buf = io.BytesIO() +img = PILImage.new('RGB', (4000, 3000), color='purple') +img.save(buf, format='JPEG') +ok, res = test_upload('test5_large.jpg', buf.getvalue(), 'image/jpeg') +print(f" Result: {'PASS' if ok else 'FAIL'} - {res}") + +# Test 6: JPEG with long filename +print("\nTest 6: JPEG with very long filename") +buf = io.BytesIO() +img = PILImage.new('RGB', (800, 600), color='orange') +img.save(buf, format='JPEG') +long_name = 'a' * 200 + '.jpg' +ok, res = test_upload(long_name, buf.getvalue(), 'image/jpeg') +print(f" Result: {'PASS' if ok else 'FAIL'} - {res}") + +# Test 7: JPEG with EXIF data +print("\nTest 7: JPEG with EXIF orientation data") +buf = io.BytesIO() +img = PILImage.new('RGB', (800, 600), color='cyan') +try: + import piexif + exif_dict = {"0th": {piexif.ImageIFD.Orientation: 6}} + exif_bytes = piexif.dump(exif_dict) + img.save(buf, format='JPEG', exif=exif_bytes) +except ImportError: + print(" (piexif not available, using plain JPEG)") + img.save(buf, format='JPEG') +ok, res = test_upload('test7_exif.jpg', buf.getvalue(), 'image/jpeg') +print(f" Result: {'PASS' if ok else 'FAIL'} - {res}") + +# Test 8: image/jpg non-standard MIME type +print("\nTest 8: Non-standard image/jpg MIME type") +buf = io.BytesIO() +img = PILImage.new('RGB', (800, 600), color='pink') +img.save(buf, format='JPEG') +ok, res = test_upload('test8.jpg', buf.getvalue(), 'image/jpg') +print(f" Result: {'PASS' if ok else 'FAIL'} - {res}") + +# Test 9: JFIF extension +print("\nTest 9: JPEG with .jfif extension") +buf = io.BytesIO() +img = PILImage.new('RGB', (800, 600), color='brown') +img.save(buf, format='JPEG') +ok, res = test_upload('test9.jfif', buf.getvalue(), 'image/jpeg') +print(f" Result: {'PASS' if ok else 'FAIL'} - {res}") + diff --git a/test_settings.py b/test_settings.py index 9a51f06ce..781dbc486 100644 --- a/test_settings.py +++ b/test_settings.py @@ -1,29 +1,2 @@ #-*- coding: utf-8 -*- -import os -DEBUG = True -PACKAGE_ROOT = os.path.abspath( os.path.dirname(__file__) ) -TMP_ROOT = os.path.abspath( os.path.join(PACKAGE_ROOT, 'tmp') ) -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(TMP_ROOT,'filer_test.sqlite3'), - }, - } -INSTALLED_APPS = [ - 'filer', - 'mptt', - 'easy_thumbnails', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.admin', - 'django.contrib.sessions', - 'django.contrib.staticfiles', -] - -ROOT_URLCONF = 'test_urls' - -MEDIA_ROOT = os.path.abspath( os.path.join(TMP_ROOT, 'media') ) -MEDIA_URL = '/media/' -STATIC_URL = '/static/' - -USE_TZ = False # because of a bug in easy-thumbnails 1.0.3 +from filer.test_settings import * diff --git a/test_urls.py b/test_urls.py deleted file mode 100644 index 40de7a552..000000000 --- a/test_urls.py +++ /dev/null @@ -1,10 +0,0 @@ -#-*- coding: utf-8 -*- -from django.conf.urls.defaults import patterns, include, url -from django.contrib import admin - -admin.autodiscover() - -urlpatterns = patterns('', - url(r'^admin/', include(admin.site.urls)), - url(r'^', include('filer.server.urls')), -) \ No newline at end of file diff --git a/tox.ini b/tox.ini new file mode 100644 index 000000000..b92f6a7c8 --- /dev/null +++ b/tox.ini @@ -0,0 +1,21 @@ +[tox] +envlist = py312 + +[testenv] +deps= + pytest + pytest-django + Django>=5.1,<5.2 + django-mptt>=0.6,<1.0 + django_polymorphic==4.0.0 + django-js-asset==2.0.0 + easy-thumbnails>=2,<3.0 + Unidecode>=0.04,<1.2 + six + filetype +commands= + pytest \ + --junitxml={toxinidir}/pytest-results.xml \ + --ds=filer.test_settings \ + --pyargs \ + {posargs} filer.tests diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 000000000..3967e7552 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,15 @@ +const path = require('path'); + +module.exports = { + entry: { + 'filer-base.bundle': './filer/static/filer/js/base.js', + }, + output: { + filename: '[name].js', + path: path.resolve(__dirname, 'filer/static/filer/js/dist'), + }, + resolve: { + modules: ['node_modules'], + }, +}; +